home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 January / enter-2004-01.iso / files / maxima-5.9.0.exe / {app} / share / maxima / 5.9.0 / emacs / maxima.el < prev    next >
Encoding:
Text File  |  2003-02-09  |  87.9 KB  |  2,631 lines

  1. ;;; maxima.el --- Major modes for writing Maxima code
  2.  
  3. ;; Copyright (C) 1998,1999 William F. Schelter
  4. ;; Copyright (C) 2001 Jay Belanger
  5.  
  6. ;; Author: William F. Schelter
  7. ;;         Jay Belanger
  8. ;; Maintainer: Jay Belanger <belanger@truman.edu>
  9. ;; Keywords: maxima
  10.  
  11. ;; This program is free software; you can redistribute it and/or
  12. ;; modify it under the terms of the GNU General Public License as
  13. ;; published by the Free Software Foundation; either version 2 of
  14. ;; the License, or (at your option) any later version.
  15. ;;          
  16. ;; This program is distributed in the hope that it will be
  17. ;; useful, but WITHOUT ANY WARRANTY; without even the implied
  18. ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  19. ;; PURPOSE.  See the GNU General Public License for more details.
  20. ;;          
  21. ;; You should have received a copy of the GNU General Public
  22. ;; License along with this program; if not, write to the Free
  23. ;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24. ;; MA 02111-1307 USA
  25. ;;
  26. ;;
  27. ;; Please send suggestions and bug reports to <belanger@truman.edu>. 
  28. ;; The latest version of this package should be available at
  29. ;; ftp://vh213601.truman.edu/pub/Maxima
  30. ;; You will need both maxima.el and maxima-font-lock.el
  31.  
  32. ;;; Commentary:
  33.  
  34. ;; This is a branch of William Schelter's maxima-mode.el
  35. ;;
  36. ;; Quick intro
  37. ;;
  38. ;; To install, put this file (as well as maxima-font-lock.el)
  39. ;; somewhere in your emacs load path.
  40. ;; To make sure that `maxima.el' is loaded when necessary, whether to
  41. ;; edit a file in maxima mode or interact with Maxima in an Emacs buffer,
  42. ;; put the lines
  43. ;;  (autoload 'maxima-mode "maxima" "Maxima mode" t)
  44. ;;  (autoload 'maxima "maxima" "Maxima interaction" t)
  45. ;; in your `.emacs' file.  If you want any file ending in `.max' to begin
  46. ;; in `maxima-mode', for example, put the line
  47. ;;  (setq auto-mode-alist (cons '("\\.max" . maxima-mode) auto-mode-alist))
  48. ;; to your `.emacs' file.
  49. ;;
  50. ;; Some variables that may have to be set in order to use the maxima help:
  51. ;;  maxima-info-dir   
  52. ;;         This should be the directory where the maxima info files are kept.
  53. ;;         By default, it is "/usr/local/info/"
  54. ;;  maxima-info-index-file
  55. ;;         This should be the name of the maxima info file that contains
  56. ;;         the index, by default, it is "maxima.info-15"
  57. ;; To allow M-x maxima-mode to put a buffer into maxima mode, add the line
  58. ;; (autoload 'maxima-mode "maxima" "Maxima editing mode" t)
  59. ;; to your .emacs file, to allow M-x maxima to start an interactive
  60. ;; maxima process, add
  61. ;; (autoload 'maxima "maxima" "Running Maxima interactively" t)
  62. ;; to your .emacs file.
  63. ;;
  64. ;; ** Maxima mode **
  65. ;; To put the current buffer into maxima-mode, type M-x maxima-mode
  66.  
  67. ;; Maxima mode provides the following motion commands:
  68. ;; M-C-a: Move to the beginning of the form.
  69. ;; M-C-e: Move to the end of the form.
  70. ;; M-C-b: Move to the beginning of the sexp.
  71. ;; M-C-f: Move to the end of the sexp.
  72.  
  73. ;; and the following miscellaneous commands.
  74. ;; M-h: Mark the current form
  75. ;; C-c): Check the current region for balanced parentheses.
  76. ;; C-cC-): Check the current form for balanced parentheses.
  77.  
  78. ;; Maxima mode has the following completions command:
  79. ;; M-TAB: Complete the Maxima symbol as much as possible, providing
  80. ;;      a completion buffer if there is more than one possible completion.
  81. ;;      If the variable `maxima-use-dynamic-complete' is non-nil, then
  82. ;;      M-TAB will cycle through possible completions.
  83.  
  84. ;; Portions of the buffer can be sent to a Maxima process.  (If a process is 
  85. ;; not running, one will be started.)
  86. ;; C-cC-r: Send the region to Maxima.
  87. ;; C-cC-b: Send the buffer to Maxima.
  88. ;; C-cC-c: Send the line to Maxima.
  89. ;; C-cC-e: Send the form to Maxima.
  90. ;; C-RET: Send the smallest set of lines which contains
  91. ;;        the cursor and contains no incomplete forms, and go to the next form.
  92. ;; M-RET:  As above, but with the region instead of the current line.
  93. ;; C-cC-l: Prompt for a file name to load into Maxima.
  94. ;;
  95. ;; When something is sent to Maxima, a buffer running an inferior Maxima 
  96. ;; process will appear.  It can also be made to appear by using the command
  97. ;; C-c C-p.
  98. ;; When a command is given to send information to Maxima, the region
  99. ;; (buffer, line, form) is first checked to make sure the parentheses
  100. ;; are balanced.  With an argument, they will not be checked first.
  101. ;; The Maxima process can be killed, after asking for confirmation 
  102. ;; with C-cC-k.  To kill without confirmation, give C-cC-k
  103. ;; an argument.
  104.  
  105. ;; By default, indentation will be to the same level as the 
  106. ;; previous line, with an additional space added for open parentheses.
  107. ;; The behaviour of indent can be changed by the command 
  108. ;; M-x maxima-change-indent-style.  The possibilities are:
  109. ;; Standard:      Simply indent
  110. ;; Perhaps smart: Tries to guess an appropriate indentation, based on
  111. ;;                open parentheses, "do" loops, etc.
  112. ;; The default can be set by setting the value of the variable 
  113. ;; "maxima-indent-style" to either 'standard or 'perhaps-smart.
  114. ;; In both cases, M-x maxima-untab will remove a level of indentation.
  115.  
  116. ;; To get help on a Maxima topic, use:
  117. ;; C-c C-d.
  118. ;; To read the Maxima info manual, use:
  119. ;; C-c C-m.
  120. ;; To get help with the symbol under point, use:
  121. ;; C-cC-h or f12.
  122. ;; To get apropos with the symbol under point, use:
  123. ;; C-cC-a or M-f12.
  124.  
  125.  
  126. ;; ** Running Maxima interactively **
  127. ;; To run Maxima interactively in a buffer, type M-x maxima
  128. ;; In the Maxima process buffer,
  129. ;; return will check the line for balanced parentheses, and send line as input.
  130. ;; Control return will send the line as input without checking for balanced
  131. ;; parentheses.
  132.  
  133. ;; <M-tab> will complete the Maxima symbol as much as possible, providing
  134. ;;      a completion buffer if there is more than one possible completion.
  135. ;;      If `maxima-use-dynamic-complete' is non-nil, then <M-tab> will
  136. ;;      cycle through possible completions.
  137.  
  138. ;; <C-M-tab> will complete the input line, based on previous input lines.
  139. ;; C-c C-d will get help on a Maxima topic.
  140. ;; C-c C-m will bring up the Maxima info manual.
  141. ;; C-cC-k will kill the process and the buffer, after asking for
  142. ;;   confirmation.  To kill without confirmation, give C-M-k an
  143. ;;   argument.
  144.  
  145. ;; To scroll through previous commands,
  146. ;; M-p will bring the previous input to the current prompt,
  147. ;; M-n will bring the next input to the prompt.
  148. ;; M-r will bring the previous input matching
  149. ;;   a regular expression to the prompt,
  150. ;; M-s will bring the next input matching
  151. ;;   a regular expression to the prompt.
  152.  
  153. ;; Debugging:
  154. ;; Maxima's source level debugging capabilities can be accessed through
  155. ;; Emacs.  A user can set a breakpoint at a line in a file (which has 
  156. ;; been loaded using, say, batchload), and then step line by line
  157. ;; from there.  The call stack may be examined, together with the 
  158. ;; variables bound at that level.  The current position in the source 
  159. ;; file will be displayed in the other half of the window.
  160. ;; The following keys are available to assist.
  161. ;; C-x C-a C-s Step one source line with display. ("Step")
  162. ;; C-x C-a C-n Step one source line (skip functions). ("Next")
  163. ;; C-x C-a TAB Step one instruction with display. ("Stepi")
  164. ;; C-x C-a C-r Continue with display.  ("Resume")
  165. ;; C-x C-a C-f Finish executing current function. ("Finish")
  166. ;; C-x C-a < Go up stack frames. ("Up")
  167. ;; C-x C-a > Go down stack frames. ("Down")
  168. ;; M-x maxima-debug-refresh Redraw the source file buffer.
  169.  
  170. ;; A breakpoint can be set to the current line in the source file
  171. ;; with the command C-x SPC.  (The command can be 
  172. ;; entered either in the source file buffer or the Maxima process
  173. ;; buffer.)
  174.  
  175. ;;; Code:
  176.  
  177. ;;;; First
  178. (defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
  179.  
  180. ;;;; The requires and provides
  181.  
  182. (require 'comint)
  183. (require 'easymenu)
  184. (require 'maxima-font-lock)
  185. (provide 'maxima)
  186.  
  187. ;;;; The variables that the user may wish to change
  188.  
  189. (defgroup maxima nil
  190.   "Maxima mode"
  191.   :prefix "maxima-"
  192.   :tag    "Maxima")
  193.  
  194. (defcustom maxima-indent-amount 2
  195.   "*The amount of each indentation level in `maxima-mode'."
  196.   :group 'maxima
  197.   :type '(integer))
  198.  
  199. (defcustom maxima-use-dynamic-complete nil
  200.   "*If non-nil, then M-TAB will complete words dynamically."
  201.   :group 'maxima
  202.   :type 'boolean)
  203.  
  204. (defcustom maxima-indent-style 'standard
  205.   "*Determines how `maxima-mode' will handle tabs.
  206. Choices are 'standard, 'perhaps-smart"
  207.   :group 'maxima
  208.   :type '(choice :menu-tag "Indent style"
  209.                  :tag      "Indent style"
  210.                  (const standard) 
  211.                  (const perhaps-smart)))
  212.  
  213. (defvar maxima-newline-style nil
  214.   "For compatability.")
  215.  
  216. (defcustom maxima-info-dir "/usr/local/info/"
  217.   "*The directory where the maxima info files are kept."
  218.   :group 'maxima
  219.   :type '(directory))
  220.  
  221. (defcustom maxima-info-index-file "maxima.info-15"
  222.   "*The info file containing the index."
  223.   :group 'maxima
  224.   :type '(file))
  225.  
  226. (defcustom maxima-command "maxima"
  227.   "*The command used to start Maxima."
  228.   :group 'maxima
  229.   :type 'file)
  230.  
  231. (defcustom maxima-use-tabs t
  232.   "*If non-nil, indentation will use tabs."
  233.   :group 'maxima
  234.   :type 'boolean)
  235.  
  236. ;;;; The other variables
  237.  
  238. (defconst maxima-temp-suffix 0
  239.   "Temporary filename suffix.  Incremented by 1 for each filename.")
  240.  
  241. (defvar inferior-maxima-process nil
  242.   "The Maxima process.")
  243.  
  244. (defvar inferior-maxima-computing-p nil
  245.   "Non-nil if Maxima process is computing.")
  246.  
  247. (defvar inferior-maxima-question-p nil)
  248.  
  249. (defvar inferior-maxima-result nil
  250.   "The last output of the Maxima process.")
  251.  
  252. (defvar inferior-maxima-lisp-level-flag nil
  253.   "Non-nil means that the inferior Maxima process is in Lisp mode.")
  254.  
  255. (defvar inferior-maxima-debug-level-flag nil
  256.   "Non-nil means that the inferior Maxima process is in debug mode.")
  257.  
  258. (defvar inferior-maxima-top-level-flag t
  259.   "Non-nil means that the inferior Maxima process is at the top level.")
  260.  
  261. (defvar inferior-maxima-use-debug nil
  262.   "Non-nil means have the debugger available.")
  263.  
  264. (defvar maxima-debug-last-frame nil)
  265.  
  266. (defvar maxima-debug-last-frame-displayed-flag t)
  267.  
  268. (defvar maxima-debug-delete-prompt-marker nil)
  269.  
  270. (defvar maxima-debug-filter-accumulator nil)
  271.  
  272. (defvar maxima-debug-overlay nil)
  273.  
  274. (defvar maxima-debug-highlight-face 'highlight)
  275.  
  276. (defvar maxima-debug-downcase-filenames
  277.   (string-match "nt[45]" system-configuration)
  278.   "Force the case to be lower when sending a break command." )
  279.  
  280. (defvar maxima-debug-dirs  nil)
  281.  
  282. (defvar maxima-name-letters "?%_a-zA-Z0-9")
  283.  
  284. (defvar maxima-special-symbol-letters "!:='")
  285.  
  286. (defvar maxima-input-end 0
  287.   "The end of the latest input that was sent to Maxima.")
  288.  
  289. (defvar maxima-real-input-end 0
  290.   "The end of the latest input that was sent to Maxima.
  291. This doesn't include answers to questions.")
  292.  
  293. (defvar inferior-maxima-exit-hook '())
  294.  
  295. ;;;; Utility functions
  296.  
  297. (defun maxima-line-beginning-position ()
  298.   (if (not (fboundp 'line-beginning-position))
  299.       (save-excursion
  300.     (beginning-of-line)
  301.     (point))
  302.     (line-beginning-position)))
  303.  
  304. (defun maxima-line-end-position ()
  305.   (if (not (fboundp 'line-end-position))
  306.       (save-excursion
  307.     (end-of-line)
  308.     (point))
  309.     (line-end-position)))
  310.  
  311. (defun maxima-form-beginning-position ()
  312.   (save-excursion
  313.     (maxima-beginning-of-form)
  314.     (point)))
  315.  
  316. (defun maxima-name-beginning ()
  317.   (save-excursion
  318.     (skip-chars-backward maxima-name-letters)
  319.     (point)))
  320.  
  321. (defun maxima-name-end ()
  322.   (save-excursion
  323.     (skip-chars-forward maxima-name-letters)
  324.     (point)))
  325.  
  326. (defun maxima-special-symbol-beginning ()
  327.   (save-excursion
  328.     (skip-chars-backward maxima-special-symbol-letters)
  329.     (point)))
  330.  
  331. (defun maxima-special-symbol-end ()
  332.   (save-excursion
  333.     (skip-chars-forward maxima-special-symbol-letters)
  334.     (point)))
  335.  
  336. (defun maxima-make-temp-name ()
  337.   "Return a unique filename."
  338.   (setq maxima-temp-suffix (+ maxima-temp-suffix 1))
  339.   (concat (concat (make-temp-name "#mz") "-")
  340.           (int-to-string maxima-temp-suffix)
  341.           ".max"))
  342.  
  343. ;;;; Maxima mode functions
  344.  
  345. ;;; Position functions
  346.  
  347. (defun maxima-in-comment-p ()
  348.   "Non-nil means that the point is in a comment."
  349.   (let ((ok t) result)
  350.     (save-excursion
  351.       (while ok
  352.     (cond ((search-backward "/" (- (point) 2000) t)
  353.            (cond ((looking-at "/\\*")
  354.               (setq result t ok nil))
  355.              ((bobp) (setq ok nil ))
  356.              ((progn (forward-char -1)
  357.                  (looking-at "\\*/"))
  358.               (setq ok nil))))
  359.           (t (setq ok nil))))
  360.       result)))
  361.  
  362. (defun maxima-in-multiline-comment-p ()
  363.   "Non-nil means that the point is in a multiline comment."
  364.   (let ((ok t) 
  365.     (bl (maxima-line-beginning-position))
  366.     (result nil))
  367.     (save-excursion
  368.       (while ok
  369.     (cond ((search-backward "/" (- (point) 2000) t)
  370.            (cond ((looking-at "/\\*")
  371.               (if (< (point) bl)
  372.               (setq result t))
  373.               (setq ok nil))
  374.              ((bobp)(setq ok nil))
  375.              ((progn (forward-char -1)
  376.                  (looking-at "\\*/"))
  377.               (setq ok nil))))
  378.           (t (setq ok nil)))))
  379.     ;; One more thing:  if the current-line begins with a close comment,
  380.     ;; don't indent it with the comment, so this should return nil.
  381.     (if result
  382.     (save-excursion
  383.       (beginning-of-line)
  384.       (if (looking-at "[ \t]*\\*/")
  385.           (setq result nil))))
  386.     result))
  387.  
  388. (defun maxima-paren-opens-block-p ()
  389.   "Non-nil means that opening parenthesis begins a \"block\" statement."
  390.   (save-excursion
  391.     (skip-chars-backward " \t")
  392.     (forward-char -5)            ;"block"
  393.     (if (looking-at "block")
  394.     t
  395.       nil)))
  396.  
  397. (defvar maxima-paren-nest (make-vector 20 nil))
  398.  
  399. (defun maxima-begin-paren ()
  400.   "Find the point of the opening parenthesis for the point."
  401.   (interactive)
  402.   (let ((ok t)(level 0)(here (point)) last (max 0))
  403.   (save-excursion
  404.     (cond ((re-search-backward "[;$]" nil t)
  405.        (skip-chars-forward ";$ \t\n")
  406.        (if (> (point) here)
  407.            (goto-char here)))
  408.       (t (goto-char (point-min))
  409.           (maxima-forward-over-comment-whitespace)
  410.           (if (> (point) here)
  411.           (goto-char here))))
  412.     (while ok
  413.       (setq last (point))
  414.       (cond ((re-search-forward "[][()]" here t)
  415.          (setq max (max level max))
  416.          (let ((ch (char-after (- (point) 1))))
  417.          (cond ((memq ch '( ?( ?[))  
  418.             (setq level (+ level 1))
  419.             (aset maxima-paren-nest level  (1- (point))))
  420.            (t
  421.             (setq level (- level 1))))))
  422.         (t (setq ok nil))))
  423.       (aref maxima-paren-nest level))))
  424.  
  425. (defun maxima-within-loop-p (pt in-paren then-loop)
  426.   "Non-nil means that the pt is within a loop that begins at the point.
  427. This means either within parenthesis, a \"do\" loop, in a \"then\"
  428. statement, or an \"else\" statement.
  429. The arguments are pt, in-paren (non-nil means that the current loop
  430. is a parentheses loop), then-loop (non-nil means that the current loop
  431. is a \"then\" statement.
  432. Okay, \"loop\" is being used loosely here."
  433.   (save-excursion
  434.     (if (maxima-end-of-loop in-paren then-loop)
  435.     (if (< pt (point))
  436.         t
  437.       nil)
  438.       t)))
  439.  
  440. (defun maxima-in-sharp-comment-line-p ()
  441.   "Non-nil means that the point is in a comment line beginning with a sharp"
  442.   (save-excursion
  443.     (beginning-of-line)
  444.     (looking-at "[ \t]*#")))
  445.  
  446.  
  447. ;;;; Motion functions
  448.  
  449. (defun maxima-forward-over-comment-whitespace ()
  450.   "Move forward over comments and whitespace."
  451.   (let ((ok t))
  452.     (while  ok
  453.       (skip-chars-forward " \t\n")
  454.       (cond ((looking-at "/\\*")
  455.          (search-forward "*/" nil t ))
  456.         ((looking-at "\n[\t ]*#")
  457.          (forward-line 1)
  458.          (end-of-line))
  459.         ((looking-at "\n")
  460.          (forward-char 1))
  461.         (t  (setq ok nil))))))
  462.  
  463. (defun maxima-back-over-comment-whitespace ()
  464.   "Move backward over comments and whitespace."
  465.   (let ((ok t))
  466.     (while  ok
  467.       (skip-chars-backward " \t\n")
  468.       (cond ((> (point) 2)
  469.          (forward-char -2)))
  470.       (cond ((looking-at "\\*/")
  471.          (search-backward "/*" ))
  472.         (t (forward-char 2) (setq ok nil))))))
  473.  
  474. (defun maxima-end-of-loop (in-paren then-loop)
  475.   "Go to the end of the current loop.
  476. The arguments are in-paren (non-nil means the loop is a parenthesis
  477. loop), and then-loop (non-nil means the loop is a then statement."
  478.   (let ((search-for "\\<do\\>\\|\\<then\\>\\|")
  479.     (keep-looking t)
  480.     end
  481.     end-mark)
  482.     (if in-paren
  483.     (setq end-mark ",")
  484.       (setq end-mark "[;$]"))
  485.     (if then-loop
  486.     (setq end-mark (concat "\\<else\\>\\|" end-mark)))
  487.     (setq search-for (concat search-for end-mark))
  488.     (skip-chars-forward " \t\n")
  489.     (if (looking-at "(")
  490.     (if (maxima-forward-sexp)
  491.         (setq end nil)
  492.       (setq end (point)))
  493.       (while keep-looking
  494.     (if (re-search-forward search-for nil t)
  495.         (if (string-match end-mark (match-string 0))
  496.         (progn
  497.           (setq end (point))
  498.           (setq keep-looking nil))
  499.           (if (not (maxima-end-of-loop in-paren 
  500.                        (string= (match-string 0) "then")))
  501.           (progn
  502.             (setq end nil)
  503.             (setq keep-looking nil))))
  504.       (setq end nil)
  505.       (setq keep-looking nil))))
  506.     end))
  507.     
  508. ;;; This next one is stolen from gud.el
  509. (defun maxima-forward-sexp ()
  510.   "Version of `forward-sexp' that catches errors."
  511.   (condition-case nil
  512.       (forward-sexp)
  513.     (error t)))
  514.  
  515. (defun maxima-beginning-of-form ()
  516.   "Move to the beginning of the form."
  517.   (interactive)
  518.   (let ((tem (re-search-backward "[;$]" (point-min) t)))
  519.     (cond (tem
  520.        (cond ((maxima-in-comment-p)
  521.           (search-backward "/\\*" nil t)
  522.           (maxima-beginning-of-form))
  523.          ((maxima-in-sharp-comment-line-p)
  524.           (beginning-of-line)
  525.           (or (equal (point) (point-min)) (forward-char -1))
  526.           (maxima-beginning-of-form))
  527.          (t  (forward-char 1))))
  528.       (t (goto-char  (point-min))))
  529.     (maxima-forward-over-comment-whitespace)))
  530.  
  531. (defun maxima-end-of-form ()
  532.   "Move to the end of the form."
  533.   (interactive)
  534.   (let ((tem (re-search-forward "[;$]" (point-max) t)))
  535.     (cond (tem
  536.        (cond ((maxima-in-comment-p)
  537.           (search-forward "*/" nil t)
  538.           (maxima-end-of-form))
  539.          ((maxima-in-sharp-comment-line-p)
  540.           (end-of-line) (forward-char 1)
  541.           (maxima-end-of-form))))
  542.       (t (error "No ; or $ at end.")))))
  543.  
  544. (defun maxima-beginning-of-sexp ()
  545.   "Move to the beginning of the current sexp."
  546.   (interactive)
  547.   (let ((pt (maxima-begin-paren)))
  548.     (if pt
  549.     (goto-char (maxima-begin-paren))
  550.       (message "No opening parenthesis."))))
  551.  
  552. (defun maxima-end-of-sexp ()
  553.   "Move to the end of the current sexp."
  554.   (interactive)
  555.   (let ((keep-looking t)
  556.     (found nil)
  557.     pt)
  558.     (save-excursion
  559.       (while (and keep-looking (search-backward "(" nil t))
  560.     (if (not (maxima-in-comment-p))
  561.         (setq keep-looking nil)))
  562.       (if keep-looking
  563.       (message "Not in parentheses.")
  564.     (setq pt (point))
  565.     (maxima-forward-sexp)
  566.     (if (= pt (point))
  567.         (message "No end parentheses.")
  568.       (setq pt (- (point) 1))
  569.       (setq found t))))
  570.     (if found
  571.     (goto-char pt))))
  572.  
  573.  
  574. ;;;; Newlines and indents
  575.  
  576. (defun maxima-indent-form ()
  577.   "Indent the entire form."
  578.   (interactive)
  579.   (save-excursion
  580.     (let ((beg (progn (maxima-beginning-of-form)
  581.               (point)))
  582.       (end (progn (maxima-end-of-form) (point))))
  583.       (goto-char beg)
  584.       (while (< (point) end)
  585.     (maxima-indent-line)
  586.     (forward-line 1)))))
  587.  
  588. ;;; 'standard
  589. (defun maxima-standard-newline ()
  590.   "Insert a newline and indent following line like previous line.
  591. Unless the previous line opened a parenthesis, in which case 1 is
  592. added to the indentation, or if the previous line closed a parenthesis, 
  593. then 1 is subtracted."
  594.   (interactive)
  595.   (let ((indent (current-indentation)))
  596.     (let ((pt (maxima-line-beginning-position)))
  597.       (save-excursion
  598.     (while (re-search-backward "[()]" pt t)
  599.       (cond ((string= (match-string 0) ")")
  600.          (setq indent (- indent 1)))
  601.         ((string= (match-string 0) "(")
  602.          (setq indent (+ indent 1)))))))
  603.     (newline)
  604.     (indent-line-to (max indent 0))))
  605.  
  606. (defun maxima-standard-indent ()
  607.   "Indent the line based on the previous line.
  608. If the previous line opened a parenthesis, `maxima-indent-amount' is
  609. added to the indentation, if the previous line closed a parenthesis, 
  610. `maxima-indent-amount' is subtracted, otherwise the indentation 
  611. is the same as the previous line."
  612.   (interactive)
  613.   (let ((indent 0)
  614.         (pt))
  615.     (save-excursion
  616.       (when (= (forward-line -1) 0)
  617.         (progn
  618.           (setq indent (current-indentation))
  619.           (setq pt (maxima-line-end-position))
  620.           (while (re-search-forward "[()]" pt t)
  621.             (cond ((string= (match-string 0) ")")
  622.                    (setq indent (- indent maxima-indent-amount)))
  623.                   ((string= (match-string 0) "(")
  624.                    (setq indent (+ indent maxima-indent-amount))))))))
  625.     (save-excursion
  626.       (beginning-of-line)
  627.       (delete-horizontal-space)
  628.       (indent-line-to (max indent 0)))
  629.     (skip-chars-forward " \t")))
  630.  
  631. (defun maxima-untab ()
  632.   "Delete a level of indentation"
  633.   (interactive)
  634.   ;; Check to see if the previous maxima-indent-amount spaces are 
  635.   ;; on the same line and blank
  636.   (let ((i maxima-indent-amount)
  637.     (ok t)
  638.     (pt (point)))
  639.     (save-excursion
  640.       (while (and (> i 0) ok)
  641.     (setq i (- i 1))
  642.     (forward-char -1)
  643.     (if (not (looking-at " "))
  644.         (setq ok nil))
  645.     (if (looking-at "\n")
  646.         (setq ok nil))))
  647.     (if ok
  648.     (delete-region pt (- pt maxima-indent-amount)))))
  649.  
  650. ;;; 'perhaps-smart
  651. (defun maxima-perhaps-smart-calculate-indent ()
  652.   "Return appropriate indentation for current line as Maxima code.
  653. Returns an integer: the column to indent to."
  654.   (save-excursion
  655.     ;; Start off with an indentation of 0, then work from there.
  656.     (let ((indent 0)
  657.       (begin-construct nil)
  658.       (close-char "[;\\$()]")
  659.       (keep-looking t)
  660.       current-point
  661.       pt
  662.       mstring)
  663.       (save-excursion
  664.     (beginning-of-line)
  665.     (setq pt (maxima-begin-paren))
  666.     (setq current-point (point))
  667.     (if pt (setq close-char "[,()]"))
  668.     ;; Now, start looking backwards, find the first loop that the
  669.     ;; current point is in.
  670.     (while (and keep-looking 
  671.             (re-search-backward 
  672.              "\\<then\\>\\|\\<do\\>\\|\\<else\\>" pt t))
  673.       (setq mstring (match-string 0))
  674.       (forward-char (length mstring))
  675.       (if (maxima-within-loop-p current-point pt 
  676.                     (string= (match-string 0) "then"))
  677.           (progn 
  678.         (setq begin-construct (point))
  679.         (setq keep-looking nil)))
  680.       (backward-char (length mstring)))
  681.     ;; If begin-construct in non-nil, it tells us where the line
  682.     ;; that begins the current-construct it
  683.     (if begin-construct
  684.         (progn
  685.           (goto-char begin-construct)
  686.           (setq indent (+ maxima-indent-amount 
  687.                   (current-indentation))))
  688.       (if pt
  689.           (progn 
  690.         (goto-char pt)
  691.         (setq indent (+ 1 (current-column)))
  692.         (if (maxima-paren-opens-block-p)
  693.             (setq indent (- indent 4)))))))
  694.       ;;current-indentation?
  695.       ;; Now, we need to possibly do some adjustments.
  696.       ;; If the previous column doesn't end with close-char or a 
  697.       ;; parenthesis, assume that the current line in a continuation 
  698.       ;; of that line, and add 2 to the indentation, unless the 
  699.       ;; previous line was the beginning of the construct containing 
  700.       ;; the point or only an open parenthesis.
  701.       (save-excursion
  702.     (if (not (and begin-construct 
  703.               (< (count-lines begin-construct current-point) 2)))
  704.         (progn
  705.           (forward-line -1)
  706.           (end-of-line)
  707.               (maxima-back-over-comment-whitespace)
  708.           ;;(skip-chars-backward " \t\n")
  709.           (if (not (looking-at "^"))
  710.           (progn 
  711.             (forward-char -1)
  712.             (if (not (looking-at close-char))
  713.             (setq indent (+ maxima-indent-amount indent))))))))
  714.       ;; Adjust for comments
  715.       ;; In a multiline comment, add two spaces on indentation
  716.       (if (maxima-in-multiline-comment-p)
  717.       (setq indent (+ indent maxima-indent-amount)))
  718.       ;;Next, if the current line begins with an "else", then indent
  719.       ;; just like the beginning "then"
  720.       (save-excursion
  721.     (beginning-of-line)
  722.     (if (looking-at "[ \t]*else")
  723.         (progn
  724.           (maxima-back-over-comment-whitespace)
  725.           (forward-char -1)
  726.           (setq current-point (point))
  727.           (setq keep-looking t)
  728.           (while keep-looking
  729.         (if (re-search-backward "then" pt t)
  730.             (progn
  731.               (forward-char 4)
  732.               (if (maxima-within-loop-p current-point pt t)
  733.               (progn
  734.                 (setq indent (current-indentation))
  735.                 (setq keep-looking nil))))
  736.           (setq keep-looking nil))))))
  737.       ;; Finally, if the line is the first line, don't indent at all
  738.       (save-excursion
  739.     (beginning-of-line)
  740.     (if (= (point) 1)
  741.         (setq indent 0)))
  742.       indent)))
  743.  
  744. (defun maxima-perhaps-smart-indent (&optional whole-exp)
  745.   "Indent current line as Maxima code.
  746. With argument, indent any additional lines of the same expression
  747. rigidly along with this one."
  748.   (interactive)
  749.   (let ((indent (maxima-perhaps-smart-calculate-indent)) shift-amt beg end
  750.     (pos (- (point-max) (point))))
  751.     (beginning-of-line)
  752.     (setq beg (point))
  753.     (skip-chars-forward " \t")
  754.     (setq shift-amt (- indent (current-column)))
  755.     (if (zerop shift-amt)
  756.     nil
  757.       (delete-region beg (point))
  758.       (indent-to indent))
  759.     ;; If initial point was within line's indentation,
  760.     ;; position after the indentation.  Else stay at same point in text.
  761.     (if (> (- (point-max) pos) (point))
  762.     (goto-char (- (point-max) pos)))
  763.     ;; If desired, shift remaining lines of expression the same amount.
  764.     (and whole-exp (not (zerop shift-amt))
  765.      (save-excursion
  766.        (goto-char beg)
  767.        (forward-sexp 1)
  768.        (setq end (point))
  769.        (goto-char beg)
  770.        (forward-line 1)
  771.        (setq beg (point))
  772.        (> end beg))
  773.      (indent-code-rigidly beg end shift-amt))))
  774.  
  775. (defun maxima-perhaps-smart-indent-line ()
  776.   "Reindent the current line."
  777.   (interactive)
  778.   (save-excursion
  779.     (beginning-of-line)
  780.     (delete-horizontal-space)
  781.     (maxima-perhaps-smart-indent))
  782.   (skip-chars-forward " \t"))
  783.  
  784. (defun maxima-perhaps-smart-newline ()
  785.   "Indent current line, insert newline and go to the appropriate column."
  786.   (interactive)
  787.   (maxima-perhaps-smart-indent)
  788.   (newline)
  789.   (maxima-perhaps-smart-indent))
  790.  
  791. (cond
  792. ; ((eq maxima-newline-style 'basic)
  793. ;  (defun maxima-indent-line ()
  794. ;    (interactive)
  795. ;    (maxima-standard-indent))
  796. ;  (defun maxima-newline ()
  797. ;    (interactive)
  798. ;    (newline)))
  799.  ((eq maxima-indent-style 'standard)
  800.   (defun maxima-indent-line ()
  801.     (interactive)
  802.     (maxima-standard-indent))
  803.   (defun maxima-newline ()
  804.     (interactive)
  805.     (maxima-standard-newline)))
  806.  ((eq maxima-indent-style 'perhaps-smart)
  807.   (defun maxima-indent-line ()
  808.     (interactive)
  809.     (maxima-perhaps-smart-indent-line))
  810.   (defun maxima-newline ()
  811.     (interactive)
  812.     (maxima-perhaps-smart-newline))))
  813.  
  814. (defun maxima-change-indent-style (new-style)
  815.   "Change the newline style."
  816.   (interactive "sNewline style (insert \"s\" for standard, or \"p\" for perhaps-smart): ")
  817.   (cond
  818. ;   ((string= new-style "b")
  819. ;    (setq maxima-indent-style 'basic)
  820. ;    (defun maxima-indent-line ()
  821. ;      (interactive)
  822. ;      (maxima-standard-indent))
  823. ;    (defun maxima-newline ()
  824. ;      (interactive)
  825. ;      (newline)))
  826.    ((string= new-style "s")
  827.     (setq maxima-indent-style 'standard)
  828.     (defun maxima-indent-line ()
  829.       (interactive)
  830.       (maxima-standard-indent))
  831.     (defun maxima-newline ()
  832.       (interactive)
  833.       (maxima-standard-newline)))
  834.    ((string= new-style "p")
  835.     (setq maxima-indent-style 'perhaps-smart)
  836.     (defun maxima-indent-line ()
  837.       (interactive)
  838.       (maxima-perhaps-smart-indent))
  839.     (defun maxima-newline ()
  840.       (interactive)
  841.       (maxima-perhaps-smart-newline)))))
  842.  
  843. ;;;; Commenting
  844.  
  845. (defun maxima-insert-short-comment ()
  846.   "Prompt for a comment."
  847.   (interactive)
  848.   (let ((comment (read-string "Comment: ")))
  849.     (insert "/* " comment " */")
  850.     (maxima-newline)))
  851.  
  852. (defun maxima-insert-long-comment ()
  853.   "Insert a comment enviroment"
  854.   (interactive)
  855.   (insert "/*")
  856.   (maxima-newline)
  857.   (maxima-newline)
  858.   (insert "*/")
  859.   (forward-line -1)
  860.   (insert "  "))
  861.  
  862. (defun maxima-uncomment-region (beg end)
  863.   "`uncomment-region' to use with the menu."
  864.   (interactive "r")
  865.   (comment-region beg end (universal-argument)))
  866.  
  867.  
  868. ;;;; Help functions
  869.  
  870. (defun maxima-get-help ()
  871.   "Get help on a given subject"
  872.   (save-excursion
  873.     (beginning-of-line)
  874.     (skip-chars-forward "* ")
  875.     (setq pt (point))
  876.     (search-forward ":")
  877.     (skip-chars-backward ": ")
  878.     (setq name (buffer-substring-no-properties pt (point)))
  879.     (skip-chars-forward ": ")
  880.     (setq pt (point))
  881.     (end-of-line)
  882.     (skip-chars-backward ". ")
  883.     (setq place (buffer-substring-no-properties pt (point))))
  884.   (if (not running-xemacs)
  885.       (info (concat "(" maxima-info-dir "maxima.info)" place))
  886.     (info (concat maxima-info-dir "maxima.info"))
  887.     (search-forward place)
  888.     (Info-follow-nearest-node (point)))
  889.   (re-search-forward (concat "-.*: *" name "\\>"))
  890.   (beginning-of-line))
  891.  
  892. (defun maxima-get-fast-help (expr)
  893.   "Go directly to the help item if possible." 
  894.   (let 
  895.       ((maxima-help-buffer 
  896.     (get-buffer-create (concat "*Maxima Help*")))
  897.        (index-buffer (find-file-noselect 
  898.               (concat maxima-info-dir maxima-info-index-file)))
  899.        pt
  900.        place)
  901.     (save-excursion
  902.       (set-buffer index-buffer)
  903.       (goto-char 1)
  904.       (search-forward "Menu:")
  905.       (forward-line 1)
  906.       (beginning-of-line)
  907.       (re-search-forward (concat "\\* " expr ":") nil t)
  908.       (skip-chars-forward ": ")
  909.       (setq pt (point))
  910.       (end-of-line)
  911.       (skip-chars-backward ". ")
  912.       (setq place (buffer-substring-no-properties pt (point)))
  913.       (info (concat "(" maxima-info-dir "maxima.info)" place))
  914.       (re-search-forward (concat "-.*: " expr))
  915.       (beginning-of-line)
  916.       (kill-buffer index-buffer))))
  917.  
  918. (defun maxima-help (&optional expr1)
  919.   "Get help on a certain subject"
  920.   (interactive)
  921.   (let* ((maxima-help-buffer 
  922.       (get-buffer-create (concat "*Maxima Help*")))
  923.      (index-buffer (find-file-noselect 
  924.             (concat maxima-info-dir maxima-info-index-file)))
  925.      (have-info nil)
  926.      expr
  927.      expr-line
  928.      (lmark))
  929.     (if (not expr1) 
  930.         (setq expr (read-string "Maxima Help: ")) (setq expr expr1)) 
  931.     (set-buffer maxima-help-buffer)
  932.     (setq buffer-read-only nil)
  933.     (erase-buffer)
  934.     (insert "Maxima help for " expr "\n\n")
  935.     (insert "[RET] will get help on the subject on the given line\n")
  936.     (insert "q in the *info* buffer will return you here.\n")
  937.     (insert "q in this buffer will exit Maxima help\n\n")
  938.     (set-buffer index-buffer)
  939.     (goto-char 1)
  940.     (search-forward "Menu:")
  941.     (forward-line 1)
  942.     (beginning-of-line)
  943.     (while (re-search-forward (concat "\\*.*" expr ".*:") nil t)
  944.       (setq have-info t)
  945.       (setq expr-line  (buffer-substring-no-properties 
  946.             (maxima-line-beginning-position) 
  947.             (maxima-line-end-position)))
  948.       (save-excursion
  949.     (set-buffer maxima-help-buffer)
  950.     (insert expr-line "\n")))
  951.     (if have-info 
  952.     (progn
  953.       (set-buffer maxima-help-buffer)
  954.       (defun maxima-help-subject ()
  955.         (interactive)
  956.         (maxima-get-help))
  957.       (defun maxima-kill-help ()
  958.         (interactive)
  959.         (let ((buf (current-buffer)))
  960.           (delete-window)
  961.           (kill-buffer buf)))
  962.       (use-local-map (make-sparse-keymap))
  963.       (define-key (current-local-map) "\C-m" 'maxima-help-subject)
  964.       (define-key (current-local-map) "q" 'maxima-kill-help)
  965.       (goto-char 1)
  966.       (pop-to-buffer maxima-help-buffer)
  967.           (setq buffer-read-only t))
  968.       (kill-buffer maxima-help-buffer)
  969.       (message (concat "No help for *" expr "*")))))
  970.  
  971. (defun maxima-apropos-help ()
  972.   (interactive)
  973.   (maxima-help-dispatcher nil nil))
  974.  
  975. (defun maxima-completion-help ()
  976.   (interactive)
  977.   (maxima-help-dispatcher nil t))
  978.  
  979. (defun maxima-help-dispatcher (&optional arg1 arg2)
  980.   (interactive)
  981.   (cond
  982.    ((or (looking-at "[a-zA-Z_]")
  983.     (looking-at "?[a-zA-Z]")
  984.     (looking-at "%[a-zA-Z]"))
  985.     (if arg2 
  986.     (maxima-context-help)
  987.       (maxima-help (buffer-substring-no-properties
  988.          (maxima-name-beginning) (maxima-name-end)))))
  989.    ((looking-at "?")
  990.     (maxima-get-fast-help "\"\\?\""))
  991.    ((looking-at "#")
  992.     (maxima-get-fast-help "\"#\""))
  993.    ((looking-at "\\.")
  994.     (maxima-get-fast-help "\"\\.\""))
  995.    ((looking-at "[:=!%']")
  996.     (let ((expr (buffer-substring-no-properties
  997.              (maxima-special-symbol-beginning) (maxima-special-symbol-end))))
  998.       (cond
  999.        ((or (string= expr "%") (string= expr "%%"))
  1000.         (maxima-get-fast-help expr)) ; % and %% are without double quotes
  1001.        ((string= expr "''")
  1002.         (maxima-get-fast-help "\"")) ; "''" is called """ in the manual
  1003.        ((or (string= expr ":") (string= expr "::") 
  1004.                 (string= expr ":=") (string= expr "::=") 
  1005.                 (string= expr "=") (string= expr "!") (string= expr "!!"))  
  1006.         (maxima-get-fast-help (concat "\"" expr "\"")))
  1007.        (t (error "no help for %s" expr)))))
  1008.    (arg1
  1009.     (error "No help for %s" (char-to-string (char-after (point)))))
  1010.    (t                    ; point is behind a name? 
  1011.     (save-excursion
  1012.       (progn
  1013.     (backward-char 1)
  1014.     (maxima-help-dispatcher t arg2))))))
  1015.  
  1016. (defun maxima-context-help ()
  1017.   (interactive)
  1018.   (let* ((stub  (buffer-substring-no-properties 
  1019.          (maxima-name-beginning) (maxima-name-end)))
  1020.      (completions (all-completions (downcase stub) maxima-symbols)))
  1021.     (setq completions 
  1022.       (mapcar 
  1023.        (function upcase) completions))
  1024.     (if (member (upcase stub) completions)
  1025.     (setq completions (list (upcase stub))))
  1026.     (cond ((null completions)
  1027.        (message "No help for %s" stub))
  1028.       ((= 1 (length completions))
  1029.        (maxima-get-fast-help (car completions)))
  1030.       (t                ; There's no unique completion.
  1031.        (maxima-help-variation completions)))))
  1032.  
  1033. (defun maxima-help-variation (completions)
  1034.   "Get help on certain subjects."
  1035.   (let* ((maxima-help-buffer 
  1036.       (get-buffer-create (concat "*Maxima Help*")))
  1037.      (index-buffer (find-file-noselect 
  1038.             (concat maxima-info-dir maxima-info-index-file)))
  1039.      expr-line
  1040.      (lmark))
  1041.     (set-buffer maxima-help-buffer)
  1042.     (erase-buffer)
  1043.     (insert "Maxima help\n")
  1044.     (insert "[RET] will get help on the subject on the given line\n")
  1045.     (insert "q in the *info* buffer will return you here.\n")
  1046.     (insert "q in this buffer will exit Maxima help\n\n")
  1047.     (set-buffer index-buffer)
  1048.     (goto-char 1)
  1049.     (search-forward "Menu:")
  1050.     (forward-line 1)
  1051.     (beginning-of-line)
  1052.     (defun maxima-help-insert-line (expr)
  1053.       (re-search-forward (concat "\\* " expr ":") nil t)
  1054.       (setq expr-line  (buffer-substring-no-properties 
  1055.             (maxima-line-beginning-position) 
  1056.             (maxima-line-end-position)))
  1057.       (save-excursion
  1058.     (set-buffer maxima-help-buffer)
  1059.     (insert expr-line "\n")))
  1060.     (mapcar (function maxima-help-insert-line) completions) 
  1061.     (set-buffer maxima-help-buffer)
  1062.     (defun maxima-help-subject ()
  1063.       (interactive)
  1064.       (maxima-get-help))
  1065.     (defun maxima-kill-help ()
  1066.       (interactive)
  1067.       (let ((buf (current-buffer)))
  1068.     (delete-window)
  1069.     (kill-buffer buf)))
  1070.     (use-local-map (append (make-sparse-keymap) (current-local-map)))
  1071.     (define-key (current-local-map) "\C-m" 'maxima-help-subject)
  1072.     (define-key (current-local-map) "q" 'maxima-kill-help)
  1073.     (goto-char 1)
  1074.     (pop-to-buffer maxima-help-buffer)))
  1075.  
  1076. (defun maxima-info ()
  1077.   "Read the info file for Maxima."
  1078.   (interactive)
  1079.   (info (concat maxima-info-dir "maxima")))
  1080.  
  1081. ;;;; Completion
  1082. ;;; Use hippie-expand to help with completions
  1083. (require 'hippie-exp)
  1084. ;(require 'maxima-symbols)
  1085.  
  1086. ;;; This next one was mostly stolen from comint.el
  1087. (defun maxima-complete ()
  1088.   "Complete word from list of candidates.
  1089. A completions listing will be shown in a help buffer 
  1090. if completion is ambiguous."
  1091.   (interactive)
  1092.   (let* ((stub  (buffer-substring-no-properties 
  1093.                  (maxima-name-beginning) (point)))
  1094.      (completions (all-completions (downcase stub) maxima-symbols)))
  1095.     (setq completions 
  1096.           (mapcar 
  1097.            (function (lambda (x) (he-transfer-case stub x))) completions))
  1098.     (cond ((null completions)
  1099.        (message "No completions of %s" stub))
  1100.       ((= 1 (length completions))    ; Gotcha!
  1101.        (let ((completion (car completions)))
  1102.          (if (string-equal completion stub)
  1103.          (message "Sole completion")
  1104.            (insert (substring completion (length stub)))
  1105.            (message "Completed"))))
  1106.       (t                ; There's no unique completion.
  1107.              (comint-dynamic-list-completions completions)))))
  1108.  
  1109. (defun maxima-he-try (old)
  1110.   (interactive)
  1111.   (if (not old)
  1112.       ;;; let beg be the beginning of the word
  1113.       (progn
  1114.         (he-init-string (maxima-name-beginning) (point))
  1115.         (setq he-expand-list 
  1116.               (all-completions (downcase he-search-string) maxima-symbols))
  1117.         (setq he-expand-list 
  1118.               (mapcar (function 
  1119.                       (lambda (x) (he-transfer-case he-search-string x)))
  1120.                       he-expand-list))
  1121.         (if he-expand-list
  1122.             (he-substitute-string (car he-expand-list))
  1123.           nil))
  1124.     (setq he-expand-list (cdr he-expand-list))
  1125.     (if he-expand-list
  1126.         (he-substitute-string (car he-expand-list))
  1127.       (he-reset-string)
  1128.       nil)))
  1129.  
  1130. (fset 'maxima-dynamic-complete 
  1131.       (make-hippie-expand-function '(maxima-he-try)))
  1132.  
  1133. ;;;; Miscellaneous
  1134.  
  1135. (defun maxima-mark-form ()
  1136.   "Make the current form the region."
  1137.   (interactive)
  1138.   (maxima-beginning-of-form)
  1139.   (let ((tem (point)))
  1140.     (maxima-end-of-form)
  1141.     (set-mark (point))
  1142.     (goto-char tem)))
  1143.  
  1144. (defun maxima-check-parens (beg end)
  1145.   "Check to make sure that the parentheses are balanced in the region."
  1146.   (interactive "r")
  1147.   (let ((keep-going t)
  1148.     (level 0)
  1149.     pt
  1150.         paren)
  1151.     (save-excursion
  1152.       (goto-char beg)
  1153.       (while (and keep-going (re-search-forward "[()]" end t))
  1154.         (setq paren (char-to-string (char-before (point))))
  1155.     (if (not (maxima-in-comment-p))
  1156.         (progn
  1157.           (cond
  1158.            ((string= paren "(")
  1159.         (setq level (+ level 1)))
  1160.            ((string= paren ")")
  1161.         (setq level (- level 1))
  1162.         (setq pt (- (point) 1))
  1163.         (if (< level 0)
  1164.             (setq keep-going nil))))))))
  1165.     (cond
  1166.      ((= level 0)            ; All's fine
  1167.       t)
  1168.      ((< level 0)            ; Too many close parens
  1169.       (goto-char pt)
  1170.       (message "Mismatched parentheses")
  1171.       nil)
  1172.      ((> level 0)            ; Too many open parens
  1173.       ;; First of all, go to the last paren that isn't in a comment.
  1174.       (setq keep-going t)
  1175.       (goto-char end)
  1176.       (while keep-going
  1177.     (re-search-backward "[()]")
  1178.     (if (not (maxima-in-comment-p))
  1179.         (setq keep-going nil)))
  1180.       ;; If it is an open paren, then there's an error.
  1181.       (if (string= (match-string 0) "(")
  1182.       (progn
  1183.         (message "Mismatched parentheses")
  1184.         nil)
  1185.     ;; If it is a close paren, find the matching open paren
  1186.     (goto-char (maxima-begin-paren))
  1187.     ;; Next, find the previous open paren that isn't in a comment
  1188.     (setq keep-going t)
  1189.     (while keep-going
  1190.       (search-backward "(")
  1191.       (if (not (maxima-in-comment-p))
  1192.           (setq keep-going nil)))
  1193.     (message "Mismatched parentheses")
  1194.     nil)))))
  1195.  
  1196. (defun maxima-check-form-parens ()
  1197.   "Check to see if the parentheses in the current form are balanced."
  1198.   (interactive)
  1199.   (let (beg end)
  1200.     (save-excursion
  1201.       (maxima-beginning-of-form)
  1202.       (setq beg (point))
  1203.       (maxima-end-of-form)
  1204.       (setq end (point)))
  1205.     (maxima-check-parens beg end)))
  1206.  
  1207. (defun maxima-load-file (file)
  1208.   "Prompt for a Maxima file to load."
  1209.   (interactive "fMaxima file: ")
  1210.   (maxima-string (concat "load(\"" (expand-file-name file) "\");")))
  1211.  
  1212. ;;;; Syntax table
  1213.  
  1214. (defvar maxima-mode-syntax-table nil "")
  1215.  
  1216. (if (not maxima-mode-syntax-table)
  1217.     (let ((i 0))
  1218.       (setq maxima-mode-syntax-table (make-syntax-table))
  1219.       (modify-syntax-entry ?_ "w" maxima-mode-syntax-table)
  1220.       (modify-syntax-entry ?% "w" maxima-mode-syntax-table)
  1221.       (modify-syntax-entry ?? "w" maxima-mode-syntax-table)
  1222. ;;       (while (< i ?0)
  1223. ;;     (modify-syntax-entry i "_   " maxima-mode-syntax-table)
  1224. ;;     (setq i (1+ i)))
  1225. ;;       (setq i (1+ ?9))
  1226. ;;       (while (< i ?A)
  1227. ;;     (modify-syntax-entry i "_   " maxima-mode-syntax-table)
  1228. ;;     (setq i (1+ i)))
  1229. ;;       (setq i (1+ ?Z))
  1230. ;;       (while (< i ?a)
  1231. ;;     (modify-syntax-entry i "_   " maxima-mode-syntax-table)
  1232. ;;     (setq i (1+ i)))
  1233. ;;       (setq i (1+ ?z))
  1234. ;;       (while (< i 128)
  1235. ;;     (modify-syntax-entry i "_   " maxima-mode-syntax-table)
  1236. ;;     (setq i (1+ i)))
  1237.       (modify-syntax-entry ?  "    " maxima-mode-syntax-table)
  1238.       (modify-syntax-entry ?\t "   " maxima-mode-syntax-table)
  1239.       (modify-syntax-entry ?` "'   " maxima-mode-syntax-table)
  1240.       (modify-syntax-entry ?' "'   " maxima-mode-syntax-table)
  1241.       (modify-syntax-entry ?, "'   " maxima-mode-syntax-table)
  1242.       (modify-syntax-entry ?. "w" maxima-mode-syntax-table)
  1243.       (modify-syntax-entry ?# "'   " maxima-mode-syntax-table)
  1244.       (modify-syntax-entry ?\\ "\\" maxima-mode-syntax-table)
  1245.       (modify-syntax-entry ?/ ". 14" maxima-mode-syntax-table)
  1246.       (modify-syntax-entry ?* ". 23" maxima-mode-syntax-table)
  1247.       (modify-syntax-entry ?+ "." maxima-mode-syntax-table)
  1248.       (modify-syntax-entry ?- "." maxima-mode-syntax-table)
  1249.       (modify-syntax-entry ?= "." maxima-mode-syntax-table)
  1250.       (modify-syntax-entry ?< "." maxima-mode-syntax-table)
  1251.       (modify-syntax-entry ?> "." maxima-mode-syntax-table)
  1252.       (modify-syntax-entry ?& "." maxima-mode-syntax-table)
  1253.       (modify-syntax-entry ?| "." maxima-mode-syntax-table)
  1254.       (modify-syntax-entry ?\" "\"    " maxima-mode-syntax-table)
  1255.       (modify-syntax-entry ?\\ "\\   " maxima-mode-syntax-table)
  1256.       (modify-syntax-entry ?\( "()  " maxima-mode-syntax-table)
  1257.       (modify-syntax-entry ?\) ")(  " maxima-mode-syntax-table)
  1258.       (modify-syntax-entry ?\[ "(]  " maxima-mode-syntax-table)
  1259.       (modify-syntax-entry ?\] ")[  " maxima-mode-syntax-table)))
  1260.  
  1261.  
  1262. ;;;; Keymap
  1263.  
  1264. (defvar maxima-mode-map nil
  1265.   "The keymap for maxima-mode")
  1266.  
  1267. (if maxima-mode-map
  1268.     nil
  1269.   (let ((map (make-sparse-keymap)))
  1270.     ;; Motion
  1271.     (define-key map "\M-\C-a" 'maxima-beginning-of-form)
  1272.     (define-key map "\M-\C-e" 'maxima-end-of-form)
  1273.     (define-key map "\M-\C-b" 'maxima-beginning-of-sexp)
  1274.     (define-key map "\M-\C-f" 'maxima-end-of-sexp)
  1275.     ;; Process
  1276.     (define-key map "\C-c\C-p" 'maxima-display-buffer)
  1277.     (define-key map "\C-c\C-r" 'maxima-send-region)
  1278.     (define-key map "\C-c\C-b" 'maxima-send-buffer)
  1279.     (define-key map "\C-c\C-c" 'maxima-send-line)
  1280.     (define-key map "\C-c\C-e" 'maxima-send-form)
  1281.     (define-key map [(control return)] 
  1282.       'maxima-send-full-line-and-goto-next-form)
  1283.     (define-key map [(meta return)] 
  1284.       'maxima-send-completed-region-and-goto-next-form)
  1285.     (define-key map [(control meta return)] 'maxima-send-buffer)
  1286.     (define-key map "\C-c\C-k" 'maxima-stop)
  1287.     (define-key map "\C-c\C-l" 'maxima-load-file)
  1288.     ;; Completion
  1289.     (if maxima-use-dynamic-complete
  1290.         (define-key map (kbd "M-TAB") 'maxima-dynamic-complete)        
  1291.       (define-key map (kbd "M-TAB") 'maxima-complete))
  1292.     ;; Commenting
  1293.     (define-key map "\C-c;" 'comment-region)
  1294.     (define-key map "\C-c:" 'maxima-uncomment-region)
  1295.     (define-key map "\M-;" 'maxima-insert-short-comment)
  1296.     (define-key map "\C-c*" 'maxima-insert-long-comment)
  1297.     ;; Indentation
  1298. ;    (define-key map "\t" 'maxima-reindent-line)
  1299. ;    (define-key map "\C-m" 'maxima-newline)
  1300.     (define-key map "\M-\C-q" 'maxima-indent-form)
  1301. ;    (define-key map [(control tab)] 'maxima-untab)
  1302.     ;; Help
  1303.     (define-key map "\C-c\C-d" 'maxima-help)
  1304.     (define-key map "\C-c\C-m" 'maxima-info)
  1305.     (define-key map [(f12)] 'maxima-completion-help)
  1306.     (define-key map "\C-c\C-h" 'maxima-completion-help)
  1307.     (define-key map [(meta f12)] 'maxima-apropos-help)
  1308.     (define-key map "\C-c\C-a" 'maxima-apropos-help)
  1309.     ;; Misc
  1310.     (define-key map "\M-h" 'maxima-mark-form)
  1311.     (define-key map "\C-c\)" 'maxima-check-parens)
  1312.     (define-key map "\C-cC-\)" 'maxima-check-form-parens)
  1313.     (define-key map "\177" 'backward-delete-char-untabify)
  1314.     (define-key map "\C-x " 'maxima-debug-set-break)
  1315.     (setq maxima-mode-map map)))
  1316.  
  1317. ;;;; Menu
  1318.  
  1319. (easy-menu-define maxima-mode-menu maxima-mode-map "Maxima mode menu"
  1320.   '("Maxima"
  1321.     ("Motion"
  1322.      ["Beginning of form" maxima-beginning-of-form t]
  1323.      ["End of form" maxima-end-of-form t]
  1324.      ["Beginning of sexp" maxima-beginning-of-sexp t]
  1325.      ["End of sexp" maxima-end-of-sexp t])
  1326.     ("Process"
  1327.      ["Start process" maxima-start t]
  1328.      ["Send region" maxima-send-region t]
  1329.      ["Send buffer" maxima-send-buffer t]
  1330.      ["Send line" maxima-send-line t]
  1331.      ["Send form" maxima-send-form t]
  1332.      ["Load file" maxima-load-file t]
  1333.      "----"
  1334.      ["Display buffer" maxima-display-buffer t]
  1335.      "----"
  1336.      ["Kill process" maxima-stop t])
  1337.     ("Indentation"
  1338. ;     ["Change to basic" (maxima-change-indent-style "b")  
  1339. ;      (not (eq maxima-newline-style 'basic))]
  1340.      ["Change to standard" (maxima-change-indent-style "s")  
  1341.       (not (eq maxima-indent-style 'standard))]
  1342.      ["Change to smart" (maxima-change-indent-style "p")  
  1343.       (not (eq maxima-indent-style 'perhaps-smart))])
  1344.     ("Misc"
  1345.      ["Mark form" maxima-mark-form t]
  1346.      ["Check parens in region" maxima-check-parens t]
  1347.      ["Check parens in form" maxima-check-form-parens t]
  1348.      ["Comment region" comment-region t]
  1349.      ["Uncomment region" maxima-uncomment-region t])
  1350.     ("Help"
  1351.      ["Maxima info" maxima-info t]
  1352.      ["Help" maxima-help t])))
  1353.  
  1354.  
  1355. ;;;; Variable setup
  1356. ;;;; (These are used in both maxima-mode and inferior-maxima-mode).
  1357.  
  1358. (defvar maxima-mode-abbrev-table nil "")
  1359.  
  1360. (defun maxima-mode-variables ()
  1361.   "Sets all the necessary variables for maxima-mode"
  1362.   (set-syntax-table maxima-mode-syntax-table)
  1363.   (setq local-abbrev-table maxima-mode-abbrev-table)
  1364.   (make-local-variable 'paragraph-start)
  1365.   (setq paragraph-start (concat "^$\\|" page-delimiter))
  1366.   (make-local-variable 'paragraph-separate)
  1367.   (setq paragraph-separate paragraph-start)
  1368.   (make-local-variable 'indent-line-function)
  1369.   (setq indent-line-function 'maxima-indent-line)
  1370.   (make-local-variable 'indent-tabs-mode)
  1371.   (unless maxima-use-tabs
  1372.     (setq indent-tabs-mode nil))
  1373.   (make-local-variable 'comment-start)
  1374.   (setq comment-start "/*")
  1375.   (make-local-variable 'comment-end)
  1376.   (setq comment-end "*/")
  1377.   (make-local-variable 'comment-start-skip)
  1378.   (setq comment-start-skip "/\*+ *")
  1379.   (make-local-variable 'comment-column)
  1380.   (setq comment-column 40)
  1381.   (make-local-variable 'comment-indent-hook)
  1382.   (setq comment-indent-hook 'maxima-comment-indent))
  1383.  
  1384.  
  1385. ;;;; Maxima mode
  1386.  
  1387. (defun maxima-mode ()
  1388.   "Major mode for editing Maxima code.
  1389.  
  1390. Maxima mode provides the following motion commands:
  1391. \\[maxima-beginning-of-form]: Move to the beginning of the form.
  1392. \\[maxima-end-of-form]: Move to the end of the form.
  1393. \\[maxima-beginning-of-sexp]: Move to the beginning of the sexp.
  1394. \\[maxima-end-of-sexp]: Move to the end of the sexp.
  1395.  
  1396. and the following miscellaneous commands.
  1397. \\[maxima-mark-form]: Mark the current form
  1398. \\[maxima-check-parens]: Check the current region for balanced parentheses.
  1399. \\[maxima-check-form-parens]: Check the current form for balanced parentheses.
  1400.  
  1401. Maxima mode has the following completions commands:
  1402. M-TAB: Complete the Maxima symbol as much as possible, providing
  1403.      a completion buffer if there is more than one possible completion.
  1404.      If `maxima-use-dynamic-complete' is non-nil, then simple cycle 
  1405.      through possible completions.
  1406.  
  1407. Portions of the buffer can be sent to a Maxima process.  (If a process is 
  1408. not running, one will be started.)
  1409. \\[maxima-send-region]: Send the region to Maxima.
  1410. \\[maxima-send-buffer]: Send the buffer to Maxima.
  1411. \\[maxima-send-line]: Send the line to Maxima.
  1412. \\[maxima-send-form]: Send the form to Maxima.
  1413. \\[maxima-send-full-line-and-goto-next-form]: Send the smallest set of lines which contains
  1414.    the cursor and contains no incomplete forms, and go to the next form.
  1415. \\[maxima-send-completed-region-and-goto-next-form]:  As above, but with
  1416.    the region instead of the current line.
  1417. \\[maxima-load-file] will prompt for a filename and load it into Maxima
  1418. When something is sent to Maxima, a buffer running an inferior Maxima 
  1419. process will appear.  It can also be made to appear by using the command
  1420. \\[maxima-display-buffer].
  1421. If an argument is given to a command to send information to Maxima,
  1422. the region (buffer, line, form) will first be checked to make sure
  1423. the parentheses are balanced.
  1424. The Maxima process can be killed, after asking for confirmation 
  1425. with \\[maxima-stop].  To kill without confirmation, give \\[maxima-stop]
  1426. an argument.
  1427.  
  1428. By default, indentation will be to the same level as the 
  1429. previous line, with an additional space added for open parentheses.
  1430. The behaviour of indent can be changed by the command 
  1431. \\[maxima-change-indent-style].  The possibilities are:
  1432. Standard:      Standard indentation.
  1433. Perhaps smart: Tries to guess an appropriate indentation, based on
  1434.                open parentheses, \"do\" loops, etc.
  1435. The default can be set by setting the value of the variable 
  1436. \"maxima-indent-style\" to either 'standard or 'perhaps-smart.
  1437. In both cases, \\[maxima-untab] will remove a level of indentation.
  1438.  
  1439. To get help on a Maxima topic, use:
  1440. \\[maxima-help].
  1441. To read the Maxima info manual, use:
  1442. \\[maxima-info].
  1443. To get help with the symbol under point, use:
  1444. \\[maxima-completion-help].
  1445. To get apropos with the symbol under point, use:
  1446. \\[maxima-apropos-help].
  1447.  
  1448. \\{maxima-mode-map}
  1449. "
  1450.   (interactive)
  1451.   (kill-all-local-variables)
  1452.   (setq major-mode 'maxima-mode)
  1453.   (setq mode-name "Maxima")
  1454.   (use-local-map maxima-mode-map)
  1455.   (maxima-mode-variables)
  1456.   (cond
  1457.    ((eq maxima-newline-style 'basic)
  1458.     (setq maxima-indent-style 'standard))
  1459.    ((eq maxima-newline-style 'standard)
  1460.     (setq maxima-indent-style 'standard))
  1461.    ((eq maxima-newline-style 'perhaps-smart)
  1462.     (setq maxima-indent-style 'perhaps-smart)))
  1463.   (easy-menu-add maxima-mode-menu maxima-mode-map)
  1464.   (run-hooks 'maxima-mode-hook))
  1465.  
  1466.  
  1467. ;;;; Interacting with the Maxima process
  1468.  
  1469. ;;;; Starting and stopping
  1470.  
  1471. (defun maxima-start ()
  1472.   "Start the Maxima process."
  1473.   (interactive)
  1474.   (setq inferior-maxima-computing-p t)
  1475.   (setq inferior-maxima-question-p nil)
  1476.   (if (processp inferior-maxima-process)
  1477.       (unless (eq (process-status inferior-maxima-process) 'run)
  1478.         (delete-process inferior-maxima-process)
  1479.         (save-excursion
  1480.           (set-buffer "*maxima*")
  1481.           (erase-buffer))
  1482.         (setq inferior-maxima-process nil)))
  1483.   (unless (processp inferior-maxima-process)
  1484.     (setq maxima-input-end 0)
  1485.     (let ((mbuf (make-comint "maxima" maxima-command)))
  1486.       (save-excursion
  1487.         (set-buffer mbuf)
  1488.         (setq inferior-maxima-process (get-buffer-process mbuf))
  1489.         (while (not (maxima-new-prompt-p))
  1490.           (sleep-for 0.100))
  1491.         (inferior-maxima-mode)))))
  1492.  
  1493. (defun maxima-stop (&optional arg)
  1494.   "Kill the currently running Maxima process."
  1495.   (interactive "P")
  1496.   (if (processp inferior-maxima-process)
  1497.       (if arg
  1498.       (progn 
  1499.         (delete-process inferior-maxima-process)
  1500.         (kill-buffer "*maxima*")
  1501.         (setq inferior-maxima-process nil))
  1502.     (if (y-or-n-p "Really quit Maxima? ")
  1503.         (progn
  1504.           (delete-process inferior-maxima-process)
  1505.           (kill-buffer "*maxima*")
  1506.           (setq inferior-maxima-process nil))))))
  1507.  
  1508. ;;;; Sending information to the process
  1509.  
  1510. (defun maxima-prompt ()
  1511.   "Return the point of the last prompt in the maxima process buffer."
  1512.   (save-excursion
  1513.     (set-buffer (process-buffer inferior-maxima-process))
  1514.     (goto-char (point-max))
  1515.     (re-search-backward inferior-maxima-prompt)
  1516.     (match-end 0)))
  1517.  
  1518. (defun maxima-new-prompt-p ()
  1519.   "Check to see if there is a new prompt after the last input."
  1520.   (save-excursion
  1521.     (set-buffer (process-buffer inferior-maxima-process))
  1522.     (goto-char maxima-input-end)
  1523.     (or
  1524.      (re-search-forward inferior-maxima-prompt (point-max) t)
  1525.      (re-search-forward "?" (point-max) t)
  1526.      (re-search-forward "Inferior Maxima Finished" (point-max) t))))
  1527.  
  1528. (defun maxima-question-p ()
  1529.   "Check to see if there is a question"
  1530.   (let ((prompt))
  1531.     (save-excursion
  1532.       (set-buffer (process-buffer inferior-maxima-process))
  1533.       (goto-char (point-max))
  1534.       (re-search-backward "?" maxima-input-end t))))
  1535.  
  1536. (defun maxima-finished-p ()
  1537.   "Check to see if the Maxima process has halted"
  1538.   (not (maxima-running)))
  1539.  
  1540. (defun maxima-strip-string (string)
  1541.   "Remove any spaces or newlines at the beginning and end of the string"
  1542.   (while (or
  1543.           (string= "\n" (substring string -1))
  1544.           (string= " " (substring string -1)))
  1545.     (setq string (substring string 0 -1)))
  1546.   (while (or
  1547.           (string= "\n" (substring string 0 1))
  1548.           (string= " " (substring string 0 1)))
  1549.     (setq string (substring string 1)))
  1550.   string)
  1551.  
  1552. (defun maxima-single-string (string &optional nonewinput)
  1553.   "Send a string to the Maxima process."
  1554.   (setq string (maxima-strip-string string))
  1555.   (let ((prompt))
  1556.     (maxima-start)
  1557.     (save-excursion
  1558.       (set-buffer (process-buffer inferior-maxima-process))
  1559.       (goto-char (point-max))
  1560.       (insert string)
  1561.       (setq maxima-input-end (point))
  1562.       (unless nonewinput
  1563.         (setq maxima-real-input-end (point)))
  1564.       (comint-send-input);)
  1565.       (while (not (maxima-new-prompt-p))
  1566.         (sit-for 0.100))
  1567.       (goto-char (point-max)))
  1568.     (when (maxima-question-p)
  1569.       (let ((ans (read-string (maxima-question))))
  1570.         (unless (string-match "[;$]" ans)
  1571.           (setq ans (concat ans ";")))
  1572.         (maxima-single-string ans t)))))
  1573.  
  1574. (defun maxima-question ()
  1575.   "Return inferior-maxima-result with whitespace trimmed off the ends.
  1576. For use when the process asks a question."
  1577.   (let ((qn))
  1578.     (save-excursion
  1579.       (set-buffer (get-buffer "*maxima*"))
  1580.       (goto-char (point-max))
  1581.       (search-backward "?")
  1582.       (setq qn (buffer-substring-no-properties 
  1583.                 (maxima-line-beginning-position) (maxima-line-end-position)))
  1584.       (goto-char (point-max)))
  1585.     (concat qn " ")))
  1586.  
  1587. ;(defun maxima-get-lisp-end (string)
  1588. ;  (with-temp-buffer
  1589. ;    (insert string)
  1590. ;    (beginning-of-buffer)
  1591. ;    (search-forward ":lisp")
  1592. ;    (forward-sexp)
  1593. ;    (- (point) 1)))
  1594.  
  1595. (defun maxima-get-lisp-end (string)
  1596.   (let* ((tmpfile (maxima-make-temp-name))
  1597.          (tmpbuf (get-buffer-create tmpfile))
  1598.          (end))
  1599.     (save-excursion
  1600.       (set-buffer tmpbuf)
  1601.       (make-local-hook 'kill-buffer-hook)
  1602.       (setq kill-buffer-hook nil)
  1603.       (insert string)
  1604.       (beginning-of-buffer)
  1605.       (search-forward ":lisp")
  1606.       (forward-sexp)
  1607.       (setq end (- (point) 1)))
  1608.     (kill-buffer tmpbuf)
  1609.     end))
  1610.  
  1611. (defun maxima-send-block (stuff)
  1612.   "Send a block of code to Maxima."
  1613.   (maxima-start)
  1614.   (while (or
  1615.           (string-match "[$;]" stuff)
  1616.           (eq (string-match "[ \n]*:lisp" stuff) 0))
  1617.     (if (eq (string-match "[ \n]*:lisp" stuff) 0)
  1618.         (setq end (maxima-get-lisp-end stuff))
  1619.       (setq end (1+ (string-match "[$;]" stuff))))
  1620.     (maxima-single-string (substring stuff 0 end))
  1621.     (setq stuff (substring stuff end))))
  1622.  
  1623. ;;; Sending information to the process should be done through these
  1624. ;; next four commands
  1625.  
  1626. (defun maxima-string (string)
  1627.   "Send a string to the Maxima process."
  1628.   (setq inferior-maxima-computing-p t)
  1629.   (setq inferior-maxima-question-p nil)
  1630.   (maxima-send-block string)
  1631.   (maxima-display-buffer))
  1632.  
  1633. (defun maxima-string-nodisplay (string)
  1634.   "Send a string to the Maxima process."
  1635.   "Send a string to the Maxima process."
  1636.   (setq inferior-maxima-computing-p t)
  1637.   (setq inferior-maxima-question-p nil)
  1638.   (maxima-send-block string))
  1639.     
  1640. (defun maxima-region (beg end)
  1641.   "Send the region to the Maxima process."
  1642.   (maxima-string
  1643.    (buffer-substring-no-properties beg end)))
  1644.  
  1645. (defun maxima-region-nodisplay (beg end)
  1646.   "Send the region to the Maxima process,
  1647. do not display the maxima-buffer."
  1648.   (maxima-string-nodisplay
  1649.    (buffer-substring-no-properties beg end)))
  1650.  
  1651. (defun maxima-send-region (beg end &optional arg)
  1652.   "Send the current region to the Maxima process.
  1653. With an argument, check the parentheses first."
  1654.   (interactive "r\nP")
  1655.   (if arg
  1656.     (maxima-region beg end)
  1657.     (if (maxima-check-parens beg end)
  1658.         (maxima-region beg end))))
  1659.  
  1660.  
  1661. (defun maxima-send-buffer (&optional arg)
  1662.   "Send the buffer to the Maxima process, after checking the parentheses.
  1663. With an argument, don't check the parentheses."
  1664.   (interactive "P")
  1665.   (maxima-send-region (point-min) (point-max) arg))
  1666.  
  1667. (defun maxima-send-line (&optional arg)
  1668.   "Send the current line to the Maxima process, after checking parentheses.
  1669. With an argument, don't check parentheses."
  1670.   (interactive "P")
  1671.   (let ((b (maxima-line-beginning-position))
  1672.     (e (maxima-line-end-position)))
  1673.     (maxima-send-region b e arg)))
  1674.  
  1675. (defun maxima-send-line-nodisplay ()
  1676.   "Send the current line to the Maxima process."
  1677.   (interactive)
  1678.   (maxima-region-nodisplay (maxima-line-beginning-position)
  1679.                            (maxima-line-end-position)))
  1680.  
  1681. (defun maxima-send-form (&optional arg)
  1682.   "Send the current form to the Maxima process, checking parentheses.
  1683. With an argument, don't check parentheses."
  1684.   (interactive "P")
  1685.   (let (beg end)
  1686.     (save-excursion
  1687.       (maxima-beginning-of-form)
  1688.       (setq beg (point))
  1689.       (maxima-end-of-form)
  1690.       (setq end (point)))
  1691.     (maxima-send-region beg end arg)))
  1692.  
  1693. (defun maxima-send-full-line ()
  1694.   "Send the minimum number of lines such that the current is one of them,
  1695. and such that no line contains an incomplete form."
  1696.   (interactive)
  1697.   (let ((beg (point)) (end (point)))
  1698.     (save-excursion
  1699.       (goto-char beg)
  1700.       (beginning-of-line)
  1701.       (setq beg (point))
  1702.       (maxima-beginning-of-form)
  1703.       (while (< (point) beg) 
  1704.     (progn 
  1705.       (beginning-of-line)
  1706.       (setq beg (point))
  1707.       (maxima-beginning-of-form)))
  1708.       (goto-char end)
  1709.       (end-of-line)
  1710.       (setq end (point))
  1711.       (while (and (< (maxima-form-beginning-position) end) (< end (point-max)))
  1712.     (progn
  1713.       (forward-line 1)
  1714.       (end-of-line)
  1715.       (setq end (point))))
  1716.       (skip-chars-backward "[ \t;$]")
  1717.       (if (looking-at "[;$]")
  1718.       (maxima-send-region beg (1+ (point)))
  1719.     (error "; or $ at end"))
  1720.       end))) 
  1721.  
  1722. (defun maxima-send-full-line-and-goto-next-form ()
  1723.   "Do a maxima-send-full-line and go to the beginning of the next form."
  1724.   (interactive)
  1725.   (goto-char (maxima-send-full-line))
  1726.   (maxima-beginning-of-form))
  1727.  
  1728. (defun maxima-send-completed-region (beg end)
  1729.   "Send the marked region, but complete possibly non-complete forms at the bounderies."
  1730.   (interactive "r\nP")
  1731.   (let (beg1 end1)
  1732.     (save-excursion
  1733.       (goto-char beg)
  1734.       (maxima-beginning-of-form)
  1735.       (setq beg1 (point))
  1736.       (goto-char end)
  1737.       (maxima-end-of-form)
  1738.       (setq end1 (point))
  1739.       (maxima-send-region beg1 end1)
  1740.       end1)))
  1741.  
  1742. (defun maxima-send-completed-region-and-goto-next-form (beg end)
  1743.   "Do a maxima-send-completed-region and go to the beginning of the next form."
  1744.   (interactive "r\nP")
  1745.   (goto-char (maxima-send-completed-region beg end))
  1746.   (maxima-beginning-of-form))
  1747.  
  1748. (defun maxima-display-buffer ()
  1749.   "Display the inferior-maxima-process buffer so the recent output is visible."
  1750.   (interactive)
  1751.   (let ((origbuffer (current-buffer)))
  1752.     (if (not (processp inferior-maxima-process))
  1753.     (maxima-start))
  1754.     (pop-to-buffer (process-buffer inferior-maxima-process))
  1755.     (goto-char (point-max))
  1756. ;    (recenter (universal-argument))
  1757.     (pop-to-buffer origbuffer)))
  1758.  
  1759. ;;;; The inferior Maxima process
  1760.  
  1761. ;;;; Smart complete (this was taken from W. Schelter's smart-complete.el)
  1762.  
  1763. ;; Completion on forms in the buffer.   Does either a line or an sexp.
  1764. ;; Uses the current prompt and the beginning of what you have typed.
  1765. ;; Thus If the buffer contained
  1766.  
  1767. ;; (dbm:3) load("jo"
  1768. ;; (C11) lo("ji")
  1769. ;; (gdb) last
  1770. ;; maxima>>4
  1771. ;; /home/bil# ls 
  1772. ;; then if you are at a prompt 
  1773. ;; "(C15) l"  would match lo("ji")  only, not "last", not "ls" nor load("
  1774. ;; and the commands with the (gdb) prompt would only match ones
  1775. ;; starting with (gdb) ..
  1776.  
  1777. (defun maxima-get-match-n (i )
  1778.   (buffer-substring (match-beginning i) (match-end i)))
  1779.  
  1780. (defun maxima-smart-complete ()
  1781.   "Complete the command.
  1782. Begin to type the command and then type M-p.  You will be
  1783. offered in the minibuffer a succession of choices, which
  1784. you can say 'n' to to get the next one, or 'y' or 'space'
  1785. to grab the current one.
  1786.  
  1787.  Thus to get the last command starting with 'li' you type
  1788.  liM-py
  1789. "
  1790.   (interactive )
  1791.   (let ((point (point)) new str tem prompt)
  1792.     (save-excursion
  1793.       (forward-line 0)
  1794.       (cond ((looking-at inferior-maxima-prompt)
  1795.          (setq prompt (maxima-get-match-n 0))
  1796.          (setq str (buffer-substring (match-end 0) point)))
  1797.         (t (error "Your prompt on this line does not match prompt-pattern.")))
  1798.       (setq new (maxima-smart-complete2 prompt str)))
  1799.     (cond (new
  1800.        (delete-region (setq tem (- point (length str))) point)
  1801.        (goto-char tem)
  1802.        (insert new)))))
  1803.  
  1804. (defun maxima-smart-complete2 (prompt str)
  1805.   (let ((pt (point)) found
  1806.     (pat (concat (maxima-regexp-for-this-prompt prompt)
  1807.              "\\(" (regexp-quote str) "\\)" ))
  1808.     offered (not-yet t))
  1809.     (while (and  not-yet
  1810.          (re-search-backward pat nil t))
  1811.       (goto-char (match-beginning 1))
  1812.       (setq at (match-beginning 1))
  1813.       (goto-char at)
  1814.       (setq this (buffer-substring at
  1815.                    (save-excursion (end-of-line) (point))))
  1816.       (or  (member this offered)
  1817.        (equal this str)
  1818.        (progn (setq offered (cons this offered))
  1819.           ;; do this so the display does not shift...
  1820.           (goto-char pt)
  1821.           (setq not-yet
  1822.             (not (y-or-n-p (concat "Use: " this " "))))))
  1823.       (cond (not-yet (goto-char at) (beginning-of-line) (forward-char -1))
  1824.         (t (setq found
  1825.              (save-excursion
  1826.                (buffer-substring
  1827.             at
  1828.             (progn (goto-char at)
  1829.                    (max (save-excursion
  1830.                       (end-of-line) (point))
  1831.                     (save-excursion
  1832.                       (forward-sexp 1)(point))))))))))
  1833.     (or found (message "No more matches"))
  1834.     found))
  1835.  
  1836.  
  1837. ;; return a regexp for this prompt but with numbers replaced.
  1838.  
  1839. (defun maxima-split-string (s bag)
  1840.   (cond ((equal (length s) 0) '(""))
  1841.     ((string-match bag s)
  1842.      (if (= (match-beginning  0) 0)
  1843.          (cons "" (maxima-split-string (substring s (match-end 0)) bag))
  1844.        (cons (substring s 0 (match-beginning 0))
  1845.          (maxima-split-string (substring s (match-end 0)) bag))))
  1846.     (t (cons s nil))))
  1847.  
  1848. ;; Return a regexp which matches the current prompt, and which
  1849. ;; allows things like
  1850. ;; "/foo/bar# " to match  "any# "
  1851. ;; "(C12) " to match  "(C1002) " but not (gdb) nor "(D12) "
  1852. ;; if the prompt appears to be a pathname (ie has /) then
  1853. ;; allow any beginning, otherwise numbers match numbers...
  1854. (defun maxima-regexp-for-this-prompt (prompt)
  1855.   (let ((wild (cond ((string-match "/" prompt) "[^ >#%()]+")
  1856.             (t "[0-9]+"))))
  1857.     (let ((tem (maxima-split-string prompt wild)) (ans ""))
  1858.       (while tem
  1859.     (setq ans (concat ans (regexp-quote (car tem))))
  1860.     (cond ((cdr tem) (setq ans (concat ans wild))))
  1861.     (setq tem (cdr tem)))
  1862.       ans)))
  1863.  
  1864. ;;;; Filter and sentinel
  1865. ;;;; (Much of this was taken from dbl.el, by W. Schelter.
  1866.  
  1867. ;; You may easily create additional commands and bindings to interact
  1868. ;; with the display.  For example to put the dbl command next on \M-n
  1869. ;; (maxima-define-debug :next "\M-n")
  1870.  
  1871. ;; This causes the emacs command maxima-debug-:next to be defined, and runs
  1872. ;; maxima-debug-display-frame after the command.
  1873.  
  1874. ;; maxima-debug-display-frame is the basic display function.  
  1875. ;; It tries to display
  1876. ;; in the other window, the file and line corresponding to the current
  1877. ;; position in the dbl window.  For example after a dbl-step, it would
  1878. ;; display the line corresponding to the position for the last step.  Or
  1879. ;; if you have done a backtrace in the dbl buffer, and move the cursor
  1880. ;; into one of the frames, it would display the position corresponding to
  1881. ;; that frame.
  1882.  
  1883. ;; maxima-debug-display-frame is invoked automatically when a 
  1884. ;; filename-and-line-number appears in the output.
  1885.  
  1886. (defun maxima-running ()
  1887.   (and (processp inferior-maxima-process)
  1888.        (eq (process-status inferior-maxima-process) 'run)))
  1889.  
  1890. (defun maxima-check-level (string)
  1891.   "Tell when the process is done computing (by looking for the prompt)."
  1892.   (setq inferior-maxima-result string)
  1893.   (if (string-match inferior-maxima-prompt string) ;"^(C[0-9]+).*" string)
  1894.       (progn
  1895.         (setq inferior-maxima-computing-p nil)
  1896.         (setq inferior-maxima-question-p nil)
  1897.         (cond ((string-match "MAXIMA>>" string)
  1898.                (setq inferior-maxima-lisp-level-flag t)
  1899.                (setq inferior-maxima-top-level-flag nil)
  1900.                (setq inferior-maxima-debug-level-flag nil)) 
  1901.               ((string-match "\(dbm.*" string)
  1902.                (setq inferior-maxima-lisp-level-flag nil)
  1903.                (setq inferior-maxima-top-level-flag nil)
  1904.                (setq inferior-maxima-debug-level-flag t)) 
  1905.               (t
  1906.                (setq inferior-maxima-lisp-level-flag nil)
  1907.                (setq inferior-maxima-top-level-flag t)
  1908.                (setq inferior-maxima-debug-level-flag nil))))
  1909.     (if (string-match "?" string)
  1910.         (setq inferior-maxima-question-p t))))
  1911.  
  1912. (defun inferior-maxima-filter (string)
  1913.   (maxima-check-level string)
  1914.   (if (not inferior-maxima-debug-level-flag)
  1915.       (progn
  1916.     (if (overlayp maxima-debug-overlay)
  1917.         (delete-overlay maxima-debug-overlay))
  1918.     (setq overlay-arrow-position nil)))
  1919.   (let ((inhibit-quit t))
  1920.     (if maxima-debug-filter-accumulator
  1921.     (inferior-maxima-filter-accumulate-marker 
  1922.      (concat maxima-debug-filter-accumulator string))
  1923.       (inferior-maxima-filter-scan-input string)))
  1924.   "")
  1925.  
  1926. (defun inferior-maxima-filter-accumulate-marker (string)
  1927.   (setq maxima-debug-filter-accumulator nil)
  1928.   (if (> (length string) 1)
  1929.       (if (= (aref string 1) ?\032)
  1930.       (let ((end (string-match "\n" string)))
  1931.         (if end
  1932.         (progn
  1933.           (setq me string)
  1934.           (cond ((string-match
  1935.                   "\032\032\\([A-Za-z]?:?[^:]*\\):\\([0-9]*\\):[^\n]+\n"
  1936.               string)
  1937.              (setq maxima-debug-last-frame
  1938.                    (cons
  1939.                 (match-string 1 string)
  1940.                 (string-to-int  (match-string 2 string))))
  1941.              (cond 
  1942.               ((equal (cdr maxima-debug-last-frame)  0)
  1943.                     ;(message "got 0")
  1944.                     ;(sit-for 1)
  1945.                (delete-overlay maxima-debug-overlay)
  1946.                (setq overlay-arrow-position nil)
  1947.                (setq maxima-debug-last-frame nil))
  1948.               (t (setq maxima-debug-last-frame-displayed-flag nil)))))
  1949.           (inferior-maxima-filter-scan-input 
  1950.            (substring string (1+ end))))
  1951.           (setq maxima-debug-filter-accumulator string)))
  1952.     (inferior-maxima-filter-insert "\032")
  1953.     (inferior-maxima-filter-scan-input (substring string 1)))
  1954.     (setq maxima-debug-filter-accumulator string)))
  1955.  
  1956. (defun inferior-maxima-filter-scan-input (string)
  1957.   (if (equal string "")
  1958.       (setq maxima-debug-filter-accumulator nil)
  1959.     (let ((start (string-match "\032" string)))
  1960.       (if start
  1961.       (progn
  1962.         ;; to do fix this so that if maxima-debug-last-frame
  1963.         ;; changed, then set the current  text property..
  1964.         ;;
  1965.         (inferior-maxima-filter-insert (substring string 0 start))
  1966.         (inferior-maxima-filter-accumulate-marker 
  1967.          (substring string start)))
  1968.     (inferior-maxima-filter-insert string)))))
  1969.  
  1970. (defun inferior-maxima-filter-insert (string)
  1971.   (let (moving
  1972.     output-after-point 
  1973.     (old-buffer (current-buffer))
  1974.     start)
  1975.     (set-buffer (process-buffer inferior-maxima-process))
  1976.     ;; test to see if we will move the point.   We want that the
  1977.     ;; window-point of the buffer, should be equal to process-mark. 
  1978.     (setq moving (>= (window-point 
  1979.               (get-buffer-window (process-buffer inferior-maxima-process)))
  1980.              (- (process-mark inferior-maxima-process) 0)))
  1981.     (setq output-after-point (< (point) (process-mark inferior-maxima-process)))
  1982.     (unwind-protect
  1983.     (save-excursion
  1984.       ;; Insert the text, moving the process-marker.
  1985.       (goto-char (process-mark inferior-maxima-process))
  1986.       (setq start (point))
  1987.       (insert string)
  1988.       (set-marker (process-mark inferior-maxima-process) (point))
  1989.       (maxima-debug-maybe-delete-prompt)
  1990.       ;; Check for a filename-and-line number.
  1991.       (maxima-debug-display-frame
  1992.        ;; Don't display the specified file
  1993.        ;; unless (1) point is at or after the position where output appears
  1994.        ;; and (2) this buffer is on the screen.
  1995.        (or output-after-point
  1996.            (not (get-buffer-window (current-buffer))))
  1997.        ;; Display a file only when a new filename-and-line-number appears.
  1998.        t))
  1999.       (if moving
  2000.       (set-window-point
  2001.        (get-buffer-window (process-buffer inferior-maxima-process))
  2002.        (process-mark inferior-maxima-process)))
  2003.       (set-buffer old-buffer))))
  2004.  
  2005. (defun inferior-maxima-sentinel (proc msg)
  2006.   (cond ((null (buffer-name (process-buffer proc)))
  2007.      ;; buffer killed
  2008.      ;; Stop displaying an arrow in a source file.
  2009.      (if (overlayp maxima-debug-overlay)
  2010.          (delete-overlay maxima-debug-overlay))
  2011.      (setq overlay-arrow-position nil)
  2012.      (set-process-buffer proc nil))
  2013.     ((memq (process-status proc) '(signal exit))
  2014.      ;; Stop displaying an arrow in a source file.
  2015.      (if (overlayp maxima-debug-overlay)
  2016.          (delete-overlay maxima-debug-overlay))
  2017.      (setq overlay-arrow-position nil)
  2018.      ;; Fix the mode line.
  2019.      (setq mode-line-process
  2020.            (concat ": "
  2021.                (symbol-name (process-status proc))))
  2022.      (let* ((obuf (current-buffer)))
  2023.        ;; save-excursion isn't the right thing if
  2024.        ;;  process-buffer is current-buffer
  2025.        (unwind-protect
  2026.            (progn
  2027.          ;; Write something in *compilation* and hack its mode line,
  2028.          (set-buffer (process-buffer proc))
  2029.          ;; Force mode line redisplay soon
  2030.          (set-buffer-modified-p (buffer-modified-p))
  2031.          (if (eobp)
  2032.              (insert ?\n mode-name " " msg)
  2033.            (save-excursion
  2034.              (goto-char (point-max))
  2035.              (insert ?\n mode-name " " msg)))
  2036.          ;; If buffer and mode line will show that the process
  2037.          ;; is dead, we can delete it now.  Otherwise it
  2038.          ;; will stay around until M-x list-processes.
  2039.          (delete-process proc))
  2040.          ;; Restore old buffer, but don't restore old point
  2041.          ;; if obuf is the dbl buffer.
  2042.          (set-buffer obuf))))))
  2043.  
  2044. (defun maxima-debug-refresh ()
  2045.   "Fix a possibly garbled display, and redraw the arrow."
  2046.   (interactive)
  2047.   (redraw-display)
  2048.   (maxima-debug-display-frame))
  2049.  
  2050. (defun maxima-debug-display-frame (&optional nodisplay noauto)
  2051.   "Find, obey and delete the last filename-and-line marker from DBL.
  2052. The marker looks like \\032\\032FILENAME:LINE:CHARPOS\\n.
  2053. Obeying it means displaying in another window the specified file and line."
  2054.   (interactive)
  2055.   (and maxima-debug-last-frame (not nodisplay)
  2056.        (or (not maxima-debug-last-frame-displayed-flag) (not noauto))
  2057.        (progn (maxima-debug-display-line (car maxima-debug-last-frame) 
  2058.                      (cdr maxima-debug-last-frame))
  2059.           (setq maxima-debug-last-frame-displayed-flag t))))
  2060.  
  2061.          
  2062. ;;; Make sure the file named TRUE-FILE is in a buffer that appears on
  2063. ;; the screen and that its line LINE is visible.  Put the
  2064. ;; overlay-arrow on the line LINE in that buffer.
  2065.  
  2066. (defun maxima-debug-find-file (file)
  2067.   (cond ((file-exists-p file)
  2068.      (find-file-noselect file))
  2069.     ((get-buffer file))
  2070.     (t (find-file-noselect file))))
  2071.  
  2072. (defun maxima-debug-search-path (file dirs)
  2073.   (let ((paths (symbol-value dirs))
  2074.     true-file)
  2075.     (cond ((file-exists-p file) (setq true-file file))
  2076.       (t
  2077.        (while paths
  2078.          (let ((tem (expand-file-name file 
  2079.                       (or (car paths) default-directory))))
  2080.            (if  (file-exists-p tem) (setq true-file tem))
  2081.            (setq paths (cdr paths))))))
  2082.     (cond (true-file)
  2083.       (t (setq paths (symbol-value dirs))
  2084.          (set dirs
  2085.           (append paths
  2086.               (list 
  2087.                (file-name-directory
  2088.                 (read-file-name
  2089.                  (format "%s = %s, add path :" dirs paths))))))
  2090.          (maxima-debug-search-path file dirs)))))
  2091.  
  2092. (defun maxima-debug-find-line ()
  2093.   "Look for a file-line property.
  2094. If none is found, search for a regexp.
  2095. If the buffer is a non process buffer, just return current file 
  2096. and line number."
  2097.   (interactive)
  2098.   (save-excursion
  2099.     (end-of-line)
  2100.     (cond ((get-buffer-process (current-buffer))
  2101.        (cond
  2102.         ((save-excursion
  2103.            (beginning-of-line)
  2104.            (get-text-property (point) 'file-line)))
  2105.         ((progn (end-of-line) 
  2106.             (re-search-backward " \\([^: ]+\\):\\([0-9]+\\)" 300 nil))
  2107.          (setq file (buffer-substring (match-beginning 1) (match-end 1)))
  2108.          (setq line (buffer-substring (match-beginning 2) (match-end 2)))
  2109.          (setq line (read line))
  2110.          (and (integerp line)
  2111.           (setq file 
  2112.             (maxima-debug-search-path file 'maxima-debug-dirs))
  2113.           (list file line)))))
  2114.       (t (list (buffer-file-name) (+ 1 (count-lines (point))))))))
  2115.  
  2116. (defun maxima-debug-find-and-display-line ()
  2117.   (interactive)
  2118.   (let ((res (maxima-debug-find-line)))
  2119.     (and res (apply 'maxima-debug-display-line res))))
  2120.  
  2121. (defun maxima-debug-display-line (true-file line)
  2122.   (let* ((buffer (maxima-debug-find-file true-file))
  2123.      (window (display-buffer buffer t))
  2124.      (pos)
  2125.      (end))
  2126.     (save-excursion
  2127.       (set-buffer buffer)
  2128.       (save-restriction
  2129.     (widen)
  2130.     (goto-line line)
  2131.     (setq pos (point))
  2132.     (setq end (maxima-line-end-position))
  2133.     (if (overlayp maxima-debug-overlay)
  2134.         (delete-overlay maxima-debug-overlay))
  2135.     (setq maxima-debug-overlay (make-overlay pos end))
  2136.     (overlay-put maxima-debug-overlay 'face 
  2137.              maxima-debug-highlight-face)
  2138.     (setq overlay-arrow-string "=>")
  2139.     (or overlay-arrow-position
  2140.         (setq overlay-arrow-position (make-marker)))
  2141.     (set-marker overlay-arrow-position (point) (current-buffer)))
  2142.       (cond ((or (< pos (point-min)) (> pos (point-max)))
  2143.          (widen)
  2144.          (goto-char pos))))
  2145.     (set-window-point window overlay-arrow-position)))
  2146.  
  2147.  
  2148. (defun maxima-debug-maybe-delete-prompt ()
  2149.   (if (and maxima-debug-delete-prompt-marker
  2150.        (> (point-max) (marker-position maxima-debug-delete-prompt-marker)))
  2151.       (let (start)
  2152.     (goto-char maxima-debug-delete-prompt-marker)
  2153.     (setq start (point))
  2154.     (beginning-of-line)
  2155.     (delete-region (point) start)
  2156.     (setq maxima-debug-delete-prompt-marker nil))))
  2157.  
  2158. ;;;; Help functions
  2159.  
  2160. (defun maxima-debug-level-help ()
  2161.   "Get help on the debug level"
  2162.   (interactive)
  2163.   (let ((maxima-debug-help-buffer (get-buffer-create "Help on lisp level")))
  2164.     (set-buffer maxima-debug-help-buffer)
  2165.     (erase-buffer)
  2166.     (insert "Help on the Maxima debug level\n\n")
  2167.     (insert
  2168. "Maxima's source level debugging capabilities can be accessed through
  2169. Emacs.  A user can set a breakpoint at a line in a file (which has 
  2170. been loaded using, say, batchload), and then step line by line
  2171. from there.  The call stack may be examined, together with the 
  2172. variables bound at that level.  The current position in the source 
  2173. file will be displayed in the other half of the window.
  2174. The following keys are available to assist.
  2175. C-x C-a C-s Step one source line with display. (\"Step\")
  2176. C-x C-a C-n Step one source line (skip functions). (\"Next\")
  2177. C-x C-a TAB Step one instruction with display. (\"Stepi\")
  2178. C-x C-a C-r Continue with display.  (\"Resume\")
  2179. C-x C-a C-f Finish executing current function. (\"Finish\")
  2180. C-x C-a < Go up stack frames. (\"Up\")
  2181. C-x C-a > Go down stack frames. (\"Down\")
  2182. M-x maxima-debug-refresh Redraw the source file buffer.
  2183.  
  2184. A breakpoint can be set to the current line in the source file
  2185. with the command C-x SPC. (The command can be entered either in the 
  2186. source file buffer or the Maxima process buffer.)
  2187.  
  2188. The following is an example session with a file /tmp/joe.mac.
  2189.  
  2190.      (C1) batchload(\"/tmp/joe.mac\");
  2191.      (D1)                  /tmp/joe.mac
  2192.      (C2) :br joe
  2193.      Turning on debugging debugmode(true)
  2194.      Bkpt 0 for joe (in /tmp/joe.mac line 8)
  2195.      (C2) foo(2,3);
  2196.      Bkpt 0:(joe.mac 8)
  2197.      (dbm:1) :bt                       <-- :bt typed here gives a backtrace
  2198.      #0: joe(y=5)(joe.mac line 8)
  2199.      #1: foo(x=2,y=3)(joe.mac line 5)
  2200.      (joe.mac 9)                       <-- Here type C-xC-aC-n to advance line
  2201.      (joe.mac 10)                      <-- Here type C-xC-aC-n to advance line
  2202.                                        In the other buffer the source code
  2203.                                        appears with an arrow.
  2204.      (dbm:1) u;                        Investigate value of 'u
  2205.      28
  2206.      (dbm:1) u:33;                     Alter it to be 33
  2207.      (dbm:1) :r                        C-xC-aC-r Resumes the computation
  2208.      (D3)                      1094
  2209.  
  2210. The actual file /tmp/joe.mac is the following:
  2211.  
  2212.      foo(x,y):=(
  2213.        x:x+2,
  2214.        y:y+2,
  2215.        x:joe(y),
  2216.        x+y);
  2217.      
  2218.      joe(y):=block([u:y^2],
  2219.        u:u+3,
  2220.        u:u^2,
  2221.         u);
  2222.  
  2223. If you are looking at the file joe.mac, you may set a break point at a
  2224. certain line of that file by typing C-x SPC.  This figures out which
  2225. function your cursor is in, and then it sees which line of that
  2226. function you are on.  If you are on say line 2 of joe, then it will
  2227. insert in the other window `:br joe 2' the command to break joe at its
  2228. second line.
  2229.  
  2230. The above keystrokes are shortcuts for some keyword commands.  A
  2231. complete list of keyword commands follows; the number of arguments
  2232. taken depends on the particular command.  Also you need not type the
  2233. whole command, just enough to be unique among the keyword commands.
  2234. Thus `:br' would suffice for `:break'.  The current commands are:
  2235.  
  2236. `:break'
  2237.      Set a breakpoint in the specified FUNCTION at the specified LINE
  2238.      offset from the beginning of the function.  If FUNCTION is given
  2239.      as a string, then it is presumed to be a FILE and LINE is the
  2240.      offset from the beginning of the file.
  2241.  
  2242. `:bt'
  2243.      Backtrace.
  2244.  
  2245. `:continue'
  2246.      Continue the computation.
  2247.  
  2248. `:delete'
  2249.      Delete all breakpoints, or if arguments are supplied delete the
  2250.      specified breakpoints
  2251.  
  2252. `:disable'
  2253.      Disable the specified breakpoints, or all if none are specified
  2254.  
  2255. `:enable'
  2256.      Enable the specified breakpoints, or all if none are specified
  2257.  
  2258. `:frame'
  2259.      With an argument print the selected stack frame.  Otherwise the
  2260.      current frame.
  2261.  
  2262. `:help'
  2263.      Print help on a break command or with no arguments on all break
  2264.      commands
  2265.  
  2266. `:info'
  2267.      Undocumented
  2268.  
  2269. `:lisp'
  2270.      Evaluate the lisp form following on the line
  2271.  
  2272. `:lisp-quiet'
  2273.      Evaluate its arg as a lisp form without printing a prompt.
  2274.  
  2275. `:next'     
  2276.      Like `:step', except that subroutine calls are stepped over
  2277.  
  2278. `:quit'
  2279.      Quit this level
  2280.  
  2281. `:resume'
  2282.      Continue the computation.
  2283.  
  2284. `:step'
  2285.      Step program until it reaches a new source line
  2286.  
  2287. `:top'
  2288.      Throw to top level
  2289. ")
  2290.     (goto-char 1)
  2291.     (use-local-map (append (make-sparse-keymap) (current-local-map)))
  2292.     (define-key (current-local-map) (kbd "SPC") 'scroll-up)
  2293.     (define-key (current-local-map) "b" 'scroll-down)
  2294.     (defun maxima-kill-debug-help ()
  2295.       (interactive)
  2296.       (let ((buf (current-buffer)))
  2297.     (delete-window)
  2298.     (kill-buffer buf)))
  2299.     (define-key (current-local-map) "q" 'maxima-kill-debug-help)
  2300.     (pop-to-buffer maxima-debug-help-buffer)))
  2301.  
  2302.  
  2303. ;;;; Miscellaneous
  2304.  
  2305. (defun maxima-debug-call (command numeric)
  2306.   "Invoke COMMAND displaying source in other window."
  2307.   (interactive)
  2308.   (save-excursion
  2309.     (goto-char (point-max))
  2310.     (beginning-of-line)
  2311.     ;; to do put in hook here to recognize whether at
  2312.     ;; maxima or lisp level.
  2313.     (setq command (maxima-debug-subtitute-% command numeric))
  2314.     (goto-char (point-max))
  2315.     (setq maxima-debug-delete-prompt-marker (point-marker))
  2316.     (maxima-string command)))
  2317.  
  2318. (defun maxima-debug-subtitute-% (command n)
  2319.   (let* (result
  2320.      (in-dbl (get-buffer-process (current-buffer)))
  2321.      file-line)
  2322.     (cond ((string-match "%[fl]" command)
  2323.        (cond (in-dbl (setq file-line (maxima-debug-find-line)))
  2324.          (t (setq file-line
  2325.               (list (buffer-file-name)
  2326.                 (+ 1 (count-lines
  2327.                       (point)))))))))
  2328.     (while (and command (string-match "\\([^%]*\\)%\\([adeflp]\\)" command))
  2329.       (let ((letter (string-to-char (substring command (match-beginning 2))))
  2330.         subst)
  2331.     (cond ((eq letter ?p)
  2332.            (setq subst (if n (int-to-string n) "")))
  2333.           ((eq letter ?f)
  2334.            (setq subst (or (car file-line) "unknown-file")))
  2335.           ((eq letter ?l)
  2336.            (setq subst (if (cadr file-line)
  2337.                    (int-to-string (cadr file-line))
  2338.                  "unknown-line")))
  2339.           ((eq letter ?a)
  2340.            (setq subst (maxima-debug-read-address))))
  2341.     (setq result (concat 
  2342.               result
  2343.               (substring command (match-beginning 1) (match-end 1))
  2344.                  subst)))
  2345.       (setq command (substring command (match-end 2))))
  2346.     (concat result command)))
  2347.  
  2348. (defun inferior-maxima-check-and-send-line ()
  2349.   "Check the lines for mis-matched parentheses, then send the line."
  2350.   (interactive)
  2351.   (let ((ok nil)
  2352.     (pt (point))
  2353.     pt1)
  2354.     (save-excursion
  2355.       (end-of-line)
  2356.       (skip-chars-backward " \t")
  2357.       (forward-char -1)
  2358.       (when (looking-at "[$;]")
  2359.         (setq pt (point))
  2360.         (setq ok t)))
  2361.     (if ok
  2362.     (progn
  2363.       (save-excursion
  2364.         (re-search-backward inferior-maxima-prompt)
  2365.         (setq pt1 (point)))
  2366.       (if (maxima-check-parens pt1 pt)
  2367.               (progn
  2368.                 (setq inferior-maxima-computing-p t)
  2369.                 (setq inferior-maxima-question-p nil)
  2370.                 (comint-send-input))))
  2371.       (setq inferior-maxima-computing-p t)
  2372.       (setq inferior-maxima-question-p nil)
  2373.       (comint-send-input))))
  2374.  
  2375. (defun inferior-maxima-send-line ()
  2376.   "Send the line to the Maxima process."
  2377.   (interactive)
  2378.   (setq inferior-maxima-computing-p t)
  2379.   (setq inferior-maxima-question-p nil)
  2380.   (comint-send-input))
  2381.  
  2382. (defun inferior-maxima-bol ()
  2383.   "Go to the beginning of the line, but past the prompt."
  2384.   (interactive)
  2385.   (let ((eol (save-excursion (end-of-line) (point))))
  2386.     (forward-line 0)
  2387.     (if (and (looking-at inferior-maxima-prompt)
  2388.          (<= (match-end 0) eol))
  2389.     (goto-char (match-end 0)))))
  2390.  
  2391.  
  2392. (defun maxima-debug-set-break ()
  2393.   "Set breakpoint at this source line."
  2394.   (interactive)
  2395.   (let ((file-name (file-name-nondirectory buffer-file-name))
  2396.     (line (save-restriction
  2397.         (widen)
  2398.         (count-lines 1 (point)))))
  2399.     (and maxima-debug-downcase-filenames
  2400.      (setq file-name (downcase file-name)))
  2401.     (maxima-string (concat ":break \"" file-name "\" " line))))
  2402.  
  2403.     
  2404. (defun maxima-debug-read-address()
  2405.   "Return a string containing the core-address found in the buffer at point."
  2406.   (save-excursion
  2407.     (let ((pt (dot)) found begin)
  2408.       (setq found (if (search-backward "0x" (- pt 7) t)(dot)))
  2409.       (cond (found 
  2410.          (forward-char 2)
  2411.          (setq result
  2412.            (buffer-substring found
  2413.                      (progn (re-search-forward "[^0-9a-f]")
  2414.                         (forward-char -1)
  2415.                         (dot)))))
  2416.         (t (setq begin (progn 
  2417.                  (re-search-backward "[^0-9]") (forward-char 1)
  2418.                   (dot)))
  2419.            (forward-char 1)
  2420.            (re-search-forward "[^0-9]")
  2421.            (forward-char -1)
  2422.            (buffer-substring begin (dot)))))))
  2423.  
  2424.  
  2425. (defvar maxima-debug-commands nil
  2426.   "List of strings or functions used by maxima-send-maxima-debug-command.
  2427. It is for customization by you.")
  2428.  
  2429. (defun maxima-send-maxima-debug-command (arg)
  2430.   "This command reads the number where the cursor is positioned.  It
  2431.  then inserts this ADDR at the end of the buffer.  A numeric arg
  2432.  selects the ARG'th member COMMAND of the list dbl-print-command.  If
  2433.  COMMAND is a string, (format COMMAND ADDR) is inserted, otherwise
  2434.  (funcall COMMAND ADDR) is inserted.  eg. \"p (rtx)%s->fld[0].rtint\"
  2435.  is a possible string to be a member of maxima-debug-commands.  "
  2436.   (interactive "P")
  2437.   (let (comm addr)
  2438.     (if arg (setq comm (nth arg maxima-debug-commands)))
  2439.     (setq addr (maxima-debug-read-address))
  2440.     (if (eq (current-buffer) (process-buffer inferior-maxima-process))
  2441.     (set-mark (point)))
  2442.     (cond (comm
  2443.        (setq comm
  2444.          (if (stringp comm) (format comm addr) (funcall comm addr))))
  2445.       (t (setq comm addr)))
  2446.     (switch-to-buffer (process-buffer inferior-maxima-process))
  2447.     (goto-char (dot-max))
  2448.     (insert-string comm)))
  2449.  
  2450.  
  2451. ;;;; Keymap
  2452.  
  2453. (defvar inferior-maxima-mode-map nil)
  2454.  
  2455. (if inferior-maxima-mode-map
  2456.     nil
  2457.   (let ((map (copy-keymap comint-mode-map)))
  2458.     (define-key map "\C-a" 'inferior-maxima-bol)
  2459.     (define-key map "\C-m"  'inferior-maxima-check-and-send-line)
  2460.     (define-key map [(control return)] 'inferior-maxima-send-line)
  2461.     (if maxima-use-dynamic-complete
  2462.         (define-key map [(meta tab)] 'maxima-dynamic-complete)
  2463.       (define-key map [(meta tab)] 'maxima-complete))
  2464.     (define-key map [(meta control tab)] 'maxima-smart-complete)
  2465.     (define-key map "\C-c\C-d" 'maxima-help)
  2466.     (define-key map "\C-c\C-m" 'maxima-info)
  2467. ;    (define-key map "\C-c\C-d" 'maxima-debug-level-help)
  2468.     (define-key map "\177" 'backward-delete-char-untabify)
  2469.     (define-key map "\C-c\C-k" 'maxima-stop)
  2470.     (define-key map "\C-c\C-l" 'maxima-debug-find-and-display-line)
  2471.     (define-key map "\C-x " 'maxima-debug-set-break)
  2472.     (setq inferior-maxima-mode-map map)))
  2473.  
  2474. (defmacro maxima-define-debug (name key &optional doc)
  2475.   (let* ((fun (intern (format "maxima-debug-%s" (read name)))))
  2476.     (list 'progn
  2477.        (list 'defun fun '(arg)
  2478.         (or doc "")
  2479.         '(interactive "p")
  2480.         (list 'maxima-debug-call name 'arg))
  2481.       (list 'define-key 'inferior-maxima-mode-map key  
  2482.         (list 'quote fun)))))
  2483.  
  2484. (maxima-define-debug ":step %p"   "\C-x\C-a\C-s" 
  2485.   "Step one source line with display")
  2486. (maxima-define-debug ":stepi %p"  "\C-x\C-a\C-i" 
  2487.   "Step one instruction with display")
  2488. (maxima-define-debug ":next %p"   "\C-x\C-a\C-n" 
  2489.   "Step one source line (skip functions)")
  2490. (maxima-define-debug ":r"   "\C-x\C-a\C-r" 
  2491.   "Continue with display")
  2492. (maxima-define-debug ":finish" "\C-x\C-a\C-f" 
  2493.   "Finish executing current function")
  2494. (maxima-define-debug ":up %p"     "\C-x\C-a<"   
  2495.   "Go up N stack frames (numeric arg) with display")
  2496. (maxima-define-debug ":down %p"   "\C-x\C-a>"   
  2497.   "Go down N stack frames (numeric arg) with display")
  2498.  
  2499.  
  2500. ;;;; Menu
  2501.  
  2502. (easy-menu-define inferior-maxima-mode-menu inferior-maxima-mode-map 
  2503.           "Maxima mode menu"
  2504.   '("Maxima"
  2505.     ("Debugging"
  2506.      ["Step one line" maxima-debug-:step inferior-maxima-debug-level-flag]
  2507.      ["Step one instruction" maxima-debug-:stepi inferior-maxima-debug-level-flag]
  2508.      ["Step one source line" maxima-debug-:next inferior-maxima-debug-level-flag]
  2509.      ["Continue" maxima-debug-:r inferior-maxima-debug-level-flag]
  2510.      ["Finish" maxima-debug-:finish inferior-maxima-debug-level-flag]
  2511.      ["Up frames" maxima-debug-:up inferior-maxima-debug-level-flag]
  2512.      ["Down frames" maxima-debug-:down inferior-maxima-debug-level-flag])
  2513.     ("Help"
  2514.      ["Maxima info" maxima-info t]
  2515.      ["Help" maxima-help t]
  2516.      ["Debug level help" maxima-debug-level-help t])
  2517.     ("Quit"
  2518.      ["Kill process" maxima-stop t])))
  2519.  
  2520. ;;;; Inferior Maxima mode
  2521.  
  2522. (defvar inferior-maxima-prompt
  2523.   "\\(^([C][0-9]*) \\)\\|\\(^MAXIMA>+\\)\\|\\(^(dbm:[0-9]*) \\)" 
  2524.                     ; \\(^[^#%)>]*[#%)>]+ *\\)"
  2525.   "*Regexp to recognize prompts from the inferior Maxima") ; or lisp")
  2526.  
  2527. (defun inferior-maxima-mode ()
  2528.   "Major mode for interacting with an inferior Maxima process.
  2529.  
  2530. Return will check the line for balanced parentheses, and send line as input.
  2531. Control return will send the line as input without checking for balanced
  2532. parentheses.
  2533.  
  2534. M-TAB will complete the Maxima symbol as much as possible, providing
  2535.      a completion buffer if there is more than one possible completion.
  2536.      If `maxima-use-dynamic-complete' is non-nil, simply cycle through 
  2537.      possible completions.
  2538.  
  2539. \\[maxima-smart-complete] will complete the input line, based on previous input lines.
  2540. \\[maxima-help] will get help on a Maxima topic.
  2541. \\[maxima-info] will bring up the Maxima info manual.
  2542. \\[maxima-stop] will kill the process and the buffer, after asking for
  2543.   confirmation.  To kill without confirmation, give \\[maxima-stop] an
  2544.   argument.
  2545.  
  2546. To scroll through previous commands,
  2547. \\[comint-previous-input] will bring the previous input to the current prompt,
  2548. \\[comint-next-input] will bring the next input to the prompt.
  2549. \\[comint-previous-matching-input] will bring the previous input matching
  2550.   a regular expression to the prompt,
  2551. \\[comint-next-matching-input] will bring the next input matching
  2552.   a regular expression to the prompt.
  2553.  
  2554. Debugging:
  2555. Maxima's source level debugging capabilities can be accessed through
  2556. Emacs.  A user can set a breakpoint at a line in a file (which has 
  2557. been loaded using, say, batchload), and then step line by line
  2558. from there.  The call stack may be examined, together with the 
  2559. variables bound at that level.  The current position in the source 
  2560. file will be displayed in the other half of the window.
  2561. The following keys are available to assist.
  2562. \\[maxima-debug-:step] Step one source line with display. (\"Step\")
  2563. \\[maxima-debug-:next] Step one source line (skip functions). (\"Next\")
  2564. \\[maxima-debug-:stepi] Step one instruction with display. (\"Stepi\")
  2565. \\[maxima-debug-:r] Continue with display.  (\"Resume\")
  2566. \\[maxima-debug-:finish] Finish executing current function. (\"Finish\")
  2567. \\[maxima-debug-:up] Go up stack frames. (\"Up\")
  2568. \\[maxima-debug-:down] Go down stack frames. (\"Down\")
  2569. \\[maxima-debug-refresh] Redraw the source file buffer.
  2570.  
  2571. A breakpoint can be set to the current line in the source file
  2572. with the command \\[maxima-debug-set-break].  (The command can be 
  2573. entered either in the source file buffer or the Maxima process
  2574. buffer.)
  2575.  
  2576. A short help page on debugging can be accessed through
  2577. \\[maxima-debug-level-help]
  2578.  
  2579.  
  2580. The following commands are available:
  2581. \\{inferior-maxima-mode-map}
  2582. "
  2583.   (interactive)
  2584.   (comint-mode)
  2585.   (setq comint-prompt-regexp inferior-maxima-prompt)
  2586.   (setq major-mode 'inferior-maxima-mode)
  2587.   (setq mode-name "Inferior Maxima")
  2588.   (setq mode-line-process '(": %s"))
  2589.   (maxima-mode-variables)
  2590.   (use-local-map inferior-maxima-mode-map)
  2591.   ;; Debugging stuff
  2592.   (setq maxima-debug-last-frame nil)
  2593.   (setq maxima-debug-last-frame-displayed-flag t)
  2594.   (setq maxima-debug-delete-prompt-marker nil)
  2595.   (setq maxima-debug-filter-accumulator nil)
  2596.   (if running-xemacs
  2597.       (add-to-list 'comint-output-filter-functions 'maxima-check-level)
  2598.     (if inferior-maxima-use-debug
  2599.        (add-to-list 'comint-preoutput-filter-functions 'inferior-maxima-filter)
  2600.       (add-to-list 'comint-output-filter-functions 'maxima-check-level)))
  2601.   (unless running-xemacs
  2602.     (set-process-sentinel inferior-maxima-process 'inferior-maxima-sentinel))
  2603.   (if running-xemacs
  2604.       (add-local-hook 'kill-buffer-hook
  2605.                       (function
  2606.                        (lambda ()
  2607.                          (if (processp inferior-maxima-process)
  2608.                              (delete-process inferior-maxima-process))
  2609.                          (setq inferior-maxima-process nil)
  2610.                          (run-hooks 'inferior-maxima-exit-hook))))
  2611.     (add-hook 'kill-buffer-hook
  2612.               (function
  2613.                (lambda ()
  2614.                  (if (processp inferior-maxima-process)
  2615.                      (delete-process inferior-maxima-process))
  2616.                  (setq inferior-maxima-process nil)
  2617.                  (run-hooks 'inferior-maxima-exit-hook))) t t))
  2618.   (run-hooks 'inferior-maxima-mode-hook))
  2619.  
  2620. ;;;; Running Maxima
  2621.  
  2622. (defun maxima ()
  2623.   "Run Maxima interactively inside a buffer."
  2624.   (interactive)
  2625.   (maxima-start)
  2626.   (switch-to-buffer (process-buffer inferior-maxima-process)))
  2627.  
  2628. (provide 'maxima)
  2629.  
  2630. ;;; maxima.el ends here
  2631.